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

VxWorks

开发平台:

C/C++

  1. /* if_dc.c - DEC 21x4x Ethernet LAN network interface driver */
  2. /* Copyright 1984-1998 Wind River Systems, Inc. */
  3. /* Copyright 1996-1998 Motorola, Inc., All Rights Reserved */
  4. #include "copyright_wrs.h"
  5. /*
  6. modification history
  7. --------------------
  8. 01m,07apr98,dat  fixed man page generation.
  9. 01l,26nov97,map  added support for SENS stack.
  10. 01k,21nov97,map  update if_flags when DC_* flags are set [SPR# 9873]
  11. 01j,30oct97,map  Merged media-select changes from mtx603/dec21140/dec21140.c
  12.                  (ver 01s). Added macros for BSP interface and register access.
  13.                  Added MII interface routines.
  14. 01i,27oct97,map  Merged from mv2603/dec21140/dec21140.c (ver 01r) [SPR# 8176]
  15. 01h,24jun97,map  Fixed memory leaks. Added dropped frame counts [SPR# 8826]
  16. 01m,15dec97,map  use BSD macro to define BSD4[34]_DRIVER flag.
  17. 01l,26nov97,map  added support for SENS stack.
  18. 01k,21nov97,map  update if_flags when DC_* flags are set [SPR# 9873]
  19. 01j,30oct97,map  Merged media-select changes from mtx603/dec21140/dec21140.c
  20.                  (ver 01s). Added macros for BSP interface and register access.
  21.                  Added MII interface routines.
  22. 01i,27oct97,map  Merged from mv2603/dec21140/dec21140.c (ver 01r) [SPR# 8176]
  23. 01h,24jun97,map  Fixed memory leaks. Added dropped frame counts [SPR# 8826]
  24. 01g,06nov96,dgp  doc: final formatting
  25. 01f,01jul96,tam  moved code from dcInt to dcHandleRecvInt to reduce the amount
  26.  of code executed at interrupt level (spr #6070).
  27. 01e,19jun96,tam  added output etherhook to dcOutput (spr #6695).
  28. 01d,05sep95,vin  added filter Frame setup, added PROMISCOUS MODE to ioctl,
  29.  changed all ln references to dc, added flag DC_MULTICAST_FLAG.
  30. 01c,05apr95,vin  added AUI/10BASE-T dynamic configuration support. 
  31. 01b,31mar95,caf  changed name from "dcPci" to "dc".
  32. 01a,03mar95,vin  written.
  33. */
  34. /* 
  35. This module implements an ethernet interface driver for the DEC 21x4x family,
  36. and currently supports the following variants -- 21040, 21140, and 21140A.
  37. The DEC 21x4x PCI Ethernet controllers are inherently little-endian since they
  38. are designed for a little-endian PCI bus. While the 21040 only supports a
  39. 10Mps interface, other members of this family are dual-speed devices which
  40. support both 10 and 100 Mbps.
  41. This driver is designed to be moderately generic, operating unmodified across
  42. the range of architectures and targets supported by VxWorks; and on multiple
  43. versions of the dec21x4x family. To achieve this, the driver takes several
  44. parameters, and external support routines which are detailed below. Also
  45. stated below are assumptions made by the driver of the hardware, and if any of
  46. these assumptions are not true for your hardware, the driver will probably not
  47. function correctly.
  48. This driver supports up to 4 ethernet units per CPU, and can be
  49. configured for either big-endian or little-endian architectures.  It
  50. contains error-recovery code to handle known device errata related to DMA
  51. activity.
  52. On a dec21040, this driver configures the 10BASE-T interface by default and
  53. waits for two seconds to check the status of the link. If the link status is
  54. "fail," it then configures the AUI interface.
  55. The dec21140, and dec21140A devices support both 10 and 100Mbps and also a
  56. variety of MII and non-MII PHY interfaces. This driver reads a DEC version 2.0
  57. SROM device for PHY initialization information, and automatically configures
  58. an apropriate active PHY media.
  59. BOARD LAYOUT
  60. This device is on-board.  No jumpering diagram is necessary.
  61. EXTERNAL INTERFACE
  62. This driver provides the standard external interface with the following
  63. exceptions.  All initialization is performed within the attach routine;
  64. there is no separate initialization routine.  Therefore, in the global interface
  65. structure, the function pointer to the initialization routine is NULL.
  66. The only user-callable routine is dcattach(), which publishes the `dc'
  67. interface and initializes the driver and device.
  68. TARGET-SPECIFIC PARAMETERS
  69. .iP "bus mode"
  70. This parameter is a global variable that can be modified at run-time.
  71. The LAN control register #0 determines the bus mode of the device,
  72. allowing the support of big-endian and little-endian architectures.
  73. This parameter, defined as "ULONG dcCSR0Bmr", is the value that will
  74. be placed into device control register #0. The default is mode is little
  75. endian.
  76. For information about changing this parameter, see the manual
  77. .I "DEC  Local Area Network Controller DEC21040 or DEC21140 for PCI."
  78. .iP "base address of device registers"
  79. This parameter is passed to the driver by dcattach().
  80. .iP "interrupt vector"
  81. This parameter is passed to the driver by dcattach().
  82. This driver configures the device to generate hardware interrupts
  83. for various events within the device; thus it contains
  84. an interrupt handler routine.  The driver calls intConnect() to connect 
  85. its interrupt handler to the interrupt vector generated as a result of 
  86. the device interrupt.
  87. .iP "interrupt level"
  88. This parameter is passed to the driver by dcattach().
  89. Some targets use additional interrupt controller devices to help organize and
  90. service the various interrupt sources.  This driver avoids all board-specific
  91. knowledge of such devices.  During the driver's initialization, the external
  92. routine sysLanIntEnable() is called to perform any board-specific operations
  93. required to allow the servicing of a device interrupt.  For a description of
  94. sysLanIntEnable(), see "External Support Requirements" below.
  95. This parameter is passed to the external routine.
  96. .iP "shared memory address"
  97. This parameter is passed to the driver by dcattach().
  98. The DEC 21x4x device is a DMA type of device and typically shares access to
  99. some region of memory with the CPU.  This driver is designed for systems that
  100. directly share memory between the CPU and the DEC 21x4x.  It assumes that this
  101. shared memory is directly available to it without any arbitration or timing
  102. concerns.
  103. This parameter can be used to specify an explicit memory region for use by the
  104. DEC 21x4x device.  This should be done on hardware that restricts the DEC
  105. 21x4x device to a particular memory region.  The constant NONE can be used to
  106. indicate that there are no memory limitations, in which case, the driver
  107. attempts to allocate the shared memory from the system space.
  108. .iP "shared memory size"
  109. This parameter is passed to the driver by dcattach().
  110. This parameter can be used to explicitly limit the amount of shared
  111. memory (bytes) this driver will use.  The constant NONE can be used to
  112. indicate no specific size limitation.  This parameter is used only if
  113. a specific memory region is provided to the driver.
  114. .iP "shared memory width"
  115. This parameter is passed to the driver by dcattach().
  116. Some target hardware that restricts the shared memory region to a
  117. specific location also restricts the access width to this region by
  118. the CPU.  On these targets, performing an access of an invalid width
  119. will cause a bus error.
  120. This parameter can be used to specify the number of bytes of access
  121. width to be used by the driver during access to the shared memory.
  122. The constant NONE can be used to indicate no restrictions.
  123. Current internal support for this mechanism is not robust; implementation 
  124. may not work on all targets requiring these restrictions.
  125. .iP "shared memory buffer size"
  126. This parameter is passed to the driver by dcattach().
  127. The driver and DEC 21x4x device exchange network data in buffers.  This
  128. parameter permits the size of these individual buffers to be limited.
  129. A value of zero indicates that the default buffer size should be used.
  130. The default buffer size is large enough to hold a maximum-size Ethernet
  131. packet.
  132. .iP "pci Memory base"
  133. This parameter is passed to the driver by dcattach(). This parameter
  134. gives the base address of the main memory on the PCI bus. 
  135. .iP "dcOpMode"
  136. This parameter is passed to the driver by dcattach(). This parameter
  137. gives the mode of initialization of the device. The mode flags for both
  138. the DEC21040 and DEC21140 interfaces are listed below.  
  139. DC_PROMISCUOUS_FLAG     0x01 
  140. DC_MULTICAST_FLAG 0x02
  141. The mode flags specific to the DEC21140 interface are listed below.
  142. DC_100_MB_FLAG          0x04
  143. DC_21140_FLAG           0x08
  144. DC_SCRAMBLER_FLAG       0x10
  145. DC_PCS_FLAG             0x20
  146. DC_PS_FLAG              0x40
  147. DC_FULLDUPLEX_FLAG      0x10
  148. Loopback mode flags
  149. DC_ILOOPB_FLAG          0x100 
  150. DC_ELOOPB_FLAG          0x200
  151. DC_HBE_FLAG         0x400
  152. .iP "Ethernet address"
  153. This is obtained by the driver by reading an ethernet ROM register or the DEC
  154. serial ROM.
  155. .LP
  156. EXTERNAL SUPPORT REQUIREMENTS
  157. This driver requires one external support function:
  158. .iP "void sysLanIntEnable (int level)" "" 9 -1
  159. This routine provides a target-specific enable of the interrupt for the DEC
  160. 21x4x device.  Typically, this involves interrupt controller hardware, either
  161. internal or external to the CPU.
  162. This routine is called once via the macro SYS_INT_ENABLE().
  163. .LP
  164. INTERNAL
  165. This driver utilizes macros to access registers and certain BSP
  166. functionalities. These macros may be redefined in a wrapper file to generate a
  167. new driver module with a customized interface.
  168. .iP "SYS_INT_CONNECT"
  169. This macro is used to associate an interrupt handler to the device interrupt
  170. vector pDrvCtrl->ivec. An OK/ERROR status is returned via parameter `pResult'.
  171. .iP "SYS_INT_DISCONNECT"
  172. Currently, this macro is not used by the driver, but exists for future
  173. implementation and will be used to disconnect an interrupt handler from the
  174. device interrupt vector. An OK/ERROR status is returned via parameter, `pResult'.
  175. .iP "SYS_INT_ENABLE"
  176. This macro is used by the driver to enable device interrupts. Typically, this
  177. macro should call a BSP routine that will enable interrupts from this device.
  178. .iP "SYS_INT_DISABLE"
  179. This macro is called by the driver to disable device interrupts.
  180. .iP "DC_CSR_READ"
  181. This macro is used by the driver to read the device command status 
  182. registers. If not redefined, this macro calls the inbuilt driver function
  183. dcCsrRead().
  184. .iP "DC_CSR_WRITE"
  185. This macro is used by the driver to write to a device command status
  186. register. By default this macro calls the inbuilt driver funtion dcCsrWrite().
  187. .LP
  188. SEE ALSO: ifLib, 
  189. .I "DECchip 21040 or 21140 Ethernet LAN Controller for PCI."
  190. */
  191. #include "vxWorks.h"
  192. #include "stdlib.h"
  193. #include "taskLib.h"
  194. #include "logLib.h"
  195. #include "intLib.h"
  196. #include "netLib.h"
  197. #include "stdio.h"
  198. #include "stdlib.h"
  199. #include "sysLib.h"
  200. #include "iv.h"
  201. #include "memLib.h"
  202. #include "cacheLib.h"
  203. #include "sys/ioctl.h"
  204. #include "etherLib.h"
  205. #ifndef DOC             /* don't include when building documentation */
  206. #include "net/mbuf.h"
  207. #endif  /* DOC */
  208. #include "net/protosw.h"
  209. #include "sys/socket.h"
  210. #include "errno.h"
  211. #include "net/if.h"
  212. #include "net/route.h"
  213. #include "netinet/in.h"
  214. #include "netinet/in_systm.h"
  215. #include "netinet/in_var.h"
  216. #include "netinet/ip.h"
  217. #include "netinet/if_ether.h"
  218. #include "net/if_subr.h"
  219. #include "semLib.h"
  220. #include "drv/netif/if_dc.h"                 /* device description header */
  221. /* defines */
  222. #if (BSD == 44)
  223. #  define BSD44_DRIVER
  224. #else
  225. #  define BSD43_DRIVER
  226. #endif /* (BSD == 44) */
  227. #ifdef BSD43_DRIVER
  228. typedef struct enet_hdr
  229.     {
  230.     char dst [6];
  231.     char src [6];
  232.     USHORT type;
  233.     } ENET_HDR;
  234. #endif /* BSD43_DRIVER */
  235. #define ENET_HDR_SIZ        sizeof(ENET_HDR)
  236. #define ENET_HDR_REAL_SIZ   14
  237. #define DC_BUFSIZ      (ETHERMTU + SIZEOF_ETHERHEADER + 6)
  238. #define MAX_UNITS       4 /* maximum units supported */
  239. #define DC_L_POOL 0x10 /* number of Rx loaner buffers in pool */
  240. #define LOOP_PER_NS 4
  241. #define DELAY(count) {                                               
  242. volatile int cx = 0;                            
  243. for (cx = 0; cx < (count); cx++);               
  244. }
  245. #ifndef NSDELAY
  246. #define NSDELAY(nsec) {                                               
  247. volatile int nx = 0;                            
  248. volatile int loop = (int)(nsec*LOOP_PER_NS);    
  249. for (nx = 0; nx < loop; nx++);                  
  250. }
  251. #endif /* NSDELAY */
  252. #define DEC21140(x) (x & DC_21140_FLAG)
  253. /*
  254.  * If DC_KICKSTART_TX is TRUE the transmitter is kick-started to force a read
  255.  * of the transmit descriptors, otherwise the internal polling (1.6msec) will
  256.  * initiate a read of the descriptors.  This should be FALSE is there is any
  257.  * chance of memory latency or chip accesses detaining the DEC 21x4x DMA,
  258.  * which results in a transmitter UFLO error.  This can be changed with the
  259.  * global dcKickStartTx below.
  260.  */
  261. #define DC_KICKSTART_TX TRUE
  262. /* Cache macros */
  263. #define DC_CACHE_INVALIDATE(address, len)                               
  264.         CACHE_DRV_INVALIDATE (&pDrvCtrl->cacheFuncs, (address), (len))
  265. #define DC_CACHE_VIRT_TO_PHYS(address)                                  
  266.         CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, (address))
  267. #define DC_CACHE_PHYS_TO_VIRT(address)                                  
  268.         CACHE_DRV_PHYS_TO_VIRT (&pDrvCtrl->cacheFuncs, (address))
  269. /*
  270.  * Default macro definitions for BSP interface.
  271.  * These macros can be redefined in a wrapper file, to generate
  272.  * a new module with an optimized interface.
  273.  */
  274. #ifndef SYS_INT_CONNECT
  275. #define SYS_INT_CONNECT(pDrvCtrl, rtn, arg, pResult)                    
  276.     {                                                                   
  277.     *pResult = intConnect((VOIDFUNCPTR *)INUM_TO_IVEC (pDrvCtrl->ivec), 
  278.                           (rtn), (int) (arg));                          
  279.     }
  280. #endif /* SYS_INT_CONNECT */
  281. #ifndef SYS_INT_DISCONNECT
  282. #define SYS_INT_DISCONNECT(pDrvCtrl, rtn, arg, pResult)                 
  283.     {                                                                   
  284.     *pResult = OK;                                                      
  285.     }
  286. #endif /* SYS_INT_DISCONNECT */
  287.     
  288. #ifndef SYS_INT_ENABLE
  289. #define SYS_INT_ENABLE(pDrvCtrl)                                        
  290.     {                                                                   
  291.     IMPORT void sysLanIntEnable(int level);                             
  292.     sysLanIntEnable (pDrvCtrl->ilevel);                                 
  293.     }
  294. #endif /* SYS_INT_ENABLE */
  295. #ifndef SYS_INT_DISABLE
  296. #define SYS_INT_DISABLE(pDrvCtrl)                                       
  297.     {                                                                   
  298.     IMPORT void sysLanIntDisable(int level);                            
  299.     sysLanIntDisable (pDrvCtrl->ilevel);                                
  300.     }
  301. #endif /* SYS_INT_DISABLE */
  302.     
  303. /* memory to PCI address translation macros */
  304. #define PCI_TO_MEM_PHYS(pciAdrs)                                        
  305. ((pciAdrs) - (pDrvCtrl->pciMemBase))
  306. #define MEM_TO_PCI_PHYS(memAdrs)                                        
  307. ((memAdrs) + (pDrvCtrl->pciMemBase))
  308. #define DC_TD_INDEX_NEXT(pDrvCtrl)                                      
  309. (((pDrvCtrl)->txIndex + 1) % (pDrvCtrl)->dcNumTds)
  310. #define DC_TD_DINDEX_NEXT(pDrvCtrl)                                     
  311. (((pDrvCtrl)->txDiIndex + 1) % (pDrvCtrl)->dcNumTds)
  312. /*
  313.  * Default macro definitions for device register accesses:
  314.  * These macros can be redefined in a wrapper file, to generate
  315.  * a new module with an optimized interface.
  316.  */
  317. #ifndef DC_CSR_READ
  318. #define DC_CSR_READ(devAdrs, csrNum)                                    
  319.      dcCsrRead ((devAdrs), (csrNum))
  320. #endif /* DC_CSR_READ */
  321. #ifndef DC_CSR_WRITE
  322. #define DC_CSR_WRITE(devAdrs, csrNum, csrVal)                           
  323.      dcCsrWrite((devAdrs), (csrNum), (csrVal))
  324. #endif /* DC_CSR_WRITE */
  325. #define DC_CSR_UPDATE(devAdrs, csrNum, csrBits)                         
  326.      DC_CSR_WRITE((devAdrs), (csrNum),                               
  327.                      DC_CSR_READ((devAdrs), (csrNum)) | (csrBits))
  328. #define DC_CSR_RESET(devAdrs, csrNum, csrBits)                          
  329.      DC_CSR_WRITE((devAdrs), (csrNum),                               
  330.                      DC_CSR_READ((devAdrs), (csrNum)) & ~(csrBits))
  331.     
  332. #define DC_INT_ENABLE(devAdrs, X)                                       
  333. DC_CSR_UPDATE ((devAdrs), CSR7, (X))
  334. #define DC_INT_DISABLE(devAdrs, X)                                      
  335.      DC_CSR_RESET ((devAdrs), CSR7, (X))
  336. #define DC_SROM_WRITE(devAdrs, adrs, delay)                             
  337.      {                                                               
  338.         DC_CSR_WRITE ((devAdrs), CSR9, (adrs) | CSR9_SR | CSR9_WR);     
  339.         NSDELAY(delay);                                                 
  340.         }
  341. #define DC_SROM_READ(devAdrs)                                           
  342. ((DC_CSR_READ ((devAdrs), CSR9) & 0x08) >> 3)
  343. /* MII read/write access macros */
  344.     
  345. #define DC_MII_BIT_READ(devAdrs, pBData)                                        
  346.      {                                                                       
  347.         DC_CSR_WRITE ((devAdrs), CSR9, CSR9_MII_RD | CSR9_RD);                  
  348.         NSDELAY (100);                                                          
  349.         DC_CSR_WRITE ((devAdrs), CSR9, CSR9_MII_RD | CSR9_RD | CSR9_MDC);       
  350.         NSDELAY (100);                                                          
  351.         *(pBData) |= CSR9_MII_DBIT_RD (DC_CSR_READ ((devAdrs), CSR9));          
  352.      }
  353. #define DC_MII_BIT_WRITE(devAdrs, data)                                 
  354.      {                                                               
  355.         DC_CSR_WRITE ((devAdrs), CSR9, CSR9_MII_DBIT_WR(data) |         
  356.                       CSR9_MII_WR | CSR9_WR);                           
  357.         NSDELAY (100);                                                  
  358.         DC_CSR_WRITE ((devAdrs), CSR9, CSR9_MII_DBIT_WR(data) |         
  359.                       CSR9_MII_WR | CSR9_WR | CSR9_MDC);                
  360.         NSDELAY (100);                                                  
  361.         }
  362. #define DC_MII_RTRISTATE(devAdrs)                                       
  363. {                                                               
  364.         int retVal;                                                     
  365.         DC_MII_BIT_READ ((devAdrs), &retVal);                           
  366.         }
  367. #define DC_MII_WTRISTATE(devAdrs)                                       
  368. {                                                               
  369.         DC_MII_BIT_WRITE((devAdrs), 0x1);                               
  370.         DC_MII_BIT_WRITE((devAdrs), 0x0);                               
  371. }
  372. #define DC_MII_WRITE(devAdrs, data, bitCount)                           
  373.      {                                                               
  374.         int i=(bitCount);                                               
  375.                                                                         
  376.         while (i--)                                                     
  377.             DC_MII_BIT_WRITE ((devAdrs), ((data) >> i) & 0x1);          
  378.         }
  379. #define DC_MII_READ(devAdrs, pData, bitCount)                           
  380.      {                                                               
  381.         int i=(bitCount);                                               
  382.                                                                         
  383.         while (i--)                                                     
  384.             {                                                           
  385.             *(pData) <<= 1;                                             
  386.             DC_MII_BIT_READ ((devAdrs), (pData));                       
  387.             }                                                           
  388.         }
  389. #define BUILD_CLUSTER(pDrvCtrl, pEnetHdr, pData, len)                           
  390. build_cluster ((pData), (len), &(pDrvCtrl)->idr.ac_if, MC_LANCE,        
  391.                        (pDrvCtrl)->pRefCnt[(pDrvCtrl)->nLoanRx - 1],            
  392.                        (FUNCPTR) dcLoanFree, (int)(pDrvCtrl),                   
  393.                        (int) (pEnetHdr),                                        
  394.                        (int)(pDrvCtrl)->pRefCnt[(pDrvCtrl)->nLoanRx - 1])
  395. #ifdef BSD43_DRIVER
  396. #define DC_START_OUTPUT(pDrvCtrl)                                        
  397.      dcStartOutput (pDrvCtrl->idr.ac_if.if_unit)
  398. #else
  399. #define DC_START_OUTPUT(pDrvCtrl)                                        
  400.      dcStartOutput (pDrvCtrl)
  401. #endif
  402.     
  403. /* Typedefs for external structures that are not typedef'd in their .h files */
  404. typedef struct mbuf MBUF;
  405. typedef struct arpcom IDR;                  /* Interface Data Record wrapper */
  406. typedef struct ifnet IFNET;                 /* real Interface Data Record */
  407. typedef struct sockaddr SOCK;
  408. #ifdef DC_DEBUG
  409. typedef struct /* dc_stats */
  410.     {
  411.     /* Transmit Error Stats */
  412.     int txJbrTmo;
  413.     int txLostCarrier;
  414.     int txNoCarrier;
  415.     int txLateCollision;
  416.     int txExsCollision;
  417.     int txHeartBeatFail;
  418.     int txLinkFail;
  419.     int txUnderflow;
  420.     int txDeferred;
  421.     int txRetries;     
  422.     int txDropped;     
  423.     int txFlushCalled;
  424.     int txFlushNeeded;
  425.     int txFlushDone;   
  426.     int txQsizeMax;    
  427.     int txQsizeCur;    
  428.     /* Receive Error Stats */
  429.     int rxFiltrErr;  
  430.     int rxDescErr;   
  431.     int rxRuntFrm;   
  432.     int rxTooLong;   
  433.     int rxCollision; 
  434.     int rxDribbleBit;
  435.     int rxCrcErr;    
  436.     int rxOverflow;  
  437.     int rxMiiErr;    
  438.     int rxMissed;
  439.     int rxLatency;
  440.     int rxStart;
  441.     int rxStop;
  442.     } DC_STATS;
  443. #endif /* DC_DEBUG */
  444. /* The definition of the driver control structure */
  445. typedef struct /* drv_ctrl */
  446.     {
  447.     IDR idr; /* Interface Data Record */
  448.     int dcNumRds; /* RMD ring size */
  449.     int rxIndex;                /* index into RMD ring */
  450.     DC_RDE * rxRing; /* RMD ring */
  451.     int dcNumTds; /* TMD ring size */
  452.     int txIndex; /* index into TMD ring */
  453.     int txDiIndex; /* disposal index into TMD ring */
  454.     DC_TDE * txRing; /* TMD ring */
  455.     BOOL        attached;               /* indicates unit is attached */
  456.     BOOL txFlushScheduled;
  457.     int txCount;
  458.     SEM_ID      TxSem;                  /* transmitter semaphore */
  459.     ULONG dcOpMode; /* mode of operation */
  460.     int         ivec;                   /* interrupt vector */
  461.     int         ilevel;                 /* interrupt level */
  462.     ULONG devAdrs;                /* device structure address */
  463.     ULONG pciMemBase; /* memory base as seen from PCI*/
  464.     int         memWidth;               /* width of data port */
  465.     CACHE_FUNCS cacheFuncs;             /* cache function pointers */
  466.     int nLoanRx; /* number of Rx buffers left to loan */
  467.     char *lPool[DC_L_POOL]; /* receive loaner pool ptrs */
  468.     UINT8 *pRefCnt[DC_L_POOL]; /* stack of reference count pointers */
  469.     UINT8 refCnt[DC_L_POOL]; /* actual reference count values */
  470.     ULONG * pFltrFrm; /* pointer to setup filter frame */
  471.     MediaBlocksType dcMediaBlocks;      /* SROM Media Data */
  472. #ifdef DC_DEBUG
  473.     DC_STATS errStats;
  474. #endif /* DC_DEBUG */
  475.     } DRV_CTRL;
  476. #define DRV_CTRL_SIZ sizeof(DRV_CTRL)
  477. #define RMD_SIZ sizeof(DC_RDE)
  478. #define TMD_SIZ sizeof(DC_TDE)
  479. #define DC_FLUSH_RETRIES 5
  480. #define MAX_TX_RETRIES 2
  481. /* globals */
  482. #ifdef DC_DEBUG
  483. int dcCsrShow (int unit);
  484. int dcViewRom (ULONG devAdrs, UCHAR lineCnt, int cnt);
  485. #endif /* DC_DEBUG */
  486. ULONG dcCSR0Bmr = 0;
  487. BOOL  dcKickStartTx  = DC_KICKSTART_TX;
  488. /* locals */
  489. LOCAL DRV_CTRL  drvCtrl [MAX_UNITS]; /* array of driver control structs */
  490. LOCAL int dcNumRds  = NUM_RDS; /* number of ring descriptors */
  491. LOCAL int dcNumTds  = NUM_TDS; /* number of xmit descriptors */
  492. LOCAL int  dcLPool = DC_L_POOL;
  493. /* forward static functions */
  494. LOCAL void  dcReset (int unit);
  495. LOCAL void  dcInt (DRV_CTRL *pDrvCtrl);
  496. LOCAL void  dcHandleRecvInt (DRV_CTRL *pDrvCtrl);
  497. LOCAL void dcTxRingClean (DRV_CTRL *pDrvCtrl);
  498. LOCAL STATUS  dcRecv (DRV_CTRL *pDrvCtrl, DC_RDE *rmd);
  499. LOCAL void dcTxFlush (DRV_CTRL *pDrvCtrl);
  500. #ifdef BSD43_DRIVER
  501. LOCAL int  dcOutput (IDR *ifp, MBUF *m0, SOCK *dst);
  502. LOCAL void dcStartOutput (int unit);
  503. #else
  504. LOCAL void dcStartOutput (DRV_CTRL *pDrvCtrl);
  505. #endif /* BSD43_DRIVER */
  506. LOCAL int  dcIoctl (IDR *ifp, int cmd, caddr_t data);
  507. LOCAL int  dcChipReset (DRV_CTRL *pDrvCtrl);
  508. LOCAL DC_RDE * dcGetFullRMD (DRV_CTRL *pDrvCtrl);
  509. LOCAL void dc21040AuiTpInit (ULONG devAdrs);
  510. LOCAL void dc21140AuiMiiInit (DRV_CTRL *pDrvCtrl, 
  511.                                    ULONG devAdrs, UINT dcCSR6);
  512. LOCAL void      dcSelectMedia (DRV_CTRL *pDrvCtrl);
  513. LOCAL void  dcCsrWrite (ULONG devAdrs, int reg, ULONG value);
  514. LOCAL ULONG  dcCsrRead (ULONG devAdrs, int reg);
  515. LOCAL void  dcRestart (int unit);
  516. LOCAL STATUS  dcEnetAddrGet (ULONG devAdrs, char * enetAdrs, int len);
  517. LOCAL STATUS  dc21140EnetAddrGet (ULONG devAdrs, char * enetAdrs, int len);
  518. LOCAL void  dcLoanFree (DRV_CTRL *pDrvCtrl, char *pRxBuf, UINT8 *pRef);
  519. LOCAL int dcFltrFrmSetup (DRV_CTRL * pDrvCtrl, char * pPhysAdrsTbl, 
  520. int tblLen);
  521. LOCAL int dcFltrFrmXmit (DRV_CTRL *pDrvCtrl, char * pPhysAdrsTbl,
  522.        int tblLen);
  523. LOCAL USHORT dcMiiPhyRead (DRV_CTRL *pDrvCrl, UINT phyAdrs, UINT phyReg);
  524. LOCAL void dcMiiPhyWrite (DRV_CTRL *pDrvCtrl, UINT phyAdrs,
  525.                                UINT phyReg, USHORT data);
  526. LOCAL USHORT dcReadRom (ULONG devAdrs, UCHAR lineCnt);
  527. /*******************************************************************************
  528. *
  529. * dcInit - device initialization sequence
  530. *
  531. * RETURNS: N/A.
  532. */
  533. LOCAL void dcInit
  534.     (
  535.     ULONG devAdrs
  536.     )
  537.     {
  538.     char dummy_buffer[60];
  539.     DC_TDE tmd;
  540.     tmd.tDesc0 = 0x80000000;
  541.     tmd.tDesc1 = 0xe200003c;
  542.     tmd.tDesc2 = (ULONG)dummy_buffer;
  543.     tmd.tDesc3 = 0;
  544.     /* start xmit dummy packet, this will never go out to the physical bus */
  545.     DC_CSR_WRITE (devAdrs, CSR4, (ULONG)(&tmd));
  546.     DC_CSR_WRITE (devAdrs, CSR7, 0);
  547.     DC_CSR_WRITE (devAdrs, CSR6, 0x2642400);
  548.     DC_CSR_WRITE (devAdrs, CSR1, CSR1_TPD);      /* xmit poll demand */
  549.     DELAY(0x8000);
  550.     /*
  551.      * Reset the device while xmitting, it ensures the device will not hang
  552.      * up in its 1st xmit later on
  553.      */
  554.     DC_CSR_UPDATE (devAdrs, CSR0, CSR0_SWR);
  555.     }
  556. /*******************************************************************************
  557. *
  558. * dcattach - publish the `dc' network interface.
  559. *
  560. * This routine publishes the `dc' interface by filling in a network interface
  561. * record and adding this record to the system list.  This routine also
  562. * initializes the driver and the device to the operational state.
  563. *
  564. * The <unit> parameter is used to specify the device unit to initialize.
  565. *
  566. * The <devAdrs> is used to specify the I/O address base of the device.
  567. *
  568. * The <ivec> parameter is used to specify the interrupt vector associated
  569. * with the device interrupt.
  570. *
  571. * The <ilevel> parater is used to specify the level of the interrupt which
  572. * the device would use.
  573. *
  574. * The <memAdrs> parameter can be used to specify the location of the
  575. * memory that will be shared between the driver and the device.  The value
  576. * NONE is used to indicate that the driver should obtain the memory.
  577. *
  578. * The <memSize> parameter is valid only if the <memAdrs> parameter is not
  579. * set to NONE, in which case <memSize> indicates the size of the
  580. * provided memory region.
  581. *
  582. * The <memWidth> parameter sets the memory pool's data port width (in bytes);
  583. * if it is NONE, any data width is used.
  584. *
  585. * The <pciMemBase> parameter defines the main memory base as seen from PCI bus.
  586. * The <dcOpMode> parameter defines the mode in which the device should be
  587. * operational.
  588. *
  589. * BUGS
  590. *
  591. * To zero out DEC 21x4x data structures, this routine uses bzero(), which
  592. * ignores the <memWidth> specification and uses any size data access to write
  593. * to memory.
  594. *
  595. * RETURNS: OK or ERROR.
  596. */
  597. STATUS dcattach
  598.     (
  599.     int unit, /* unit number */
  600.     ULONG devAdrs, /* device I/O address */
  601.     int ivec, /* interrupt vector */
  602.     int ilevel, /* interrupt level */
  603.     char * memAdrs, /* address of memory pool (-1 = malloc it) */
  604.     ULONG memSize, /* only used if memory pool is NOT malloc()'d */
  605.     int memWidth, /* byte-width of data (-1 = any width) */
  606.     ULONG pciMemBase, /* main memory base as seen from PCI bus */
  607.     int dcOpMode /* mode of operation */
  608.     )
  609.     {
  610.     DRV_CTRL * pDrvCtrl; /* pointer to drvctrl */
  611.     unsigned int sz; /* temporary size holder */
  612.     char * pShMem; /* start of the device memory pool */
  613.     char * buf; /* temp buffer pointer */
  614.     void * pTemp; /* temp pointer */
  615.     DC_RDE * rmd; /* pointer to rcv descriptor */
  616.     DC_TDE * tmd; /* pointer to xmit descriptor */
  617.     int ix; /* counter */
  618.     ULONG uTemp; /* temporary storage */
  619.     int retVal;
  620.    
  621.     /* Sanity check the unit number */
  622.     if (unit < 0 || unit >= MAX_UNITS)
  623.         return (ERROR);
  624.     uTemp = 0;
  625.     /* Ensure single invocation per system life */
  626.     pDrvCtrl = & drvCtrl [unit];
  627.     if (pDrvCtrl->attached)
  628.         return (OK);
  629.     pDrvCtrl->ivec = ivec; /* interrupt vector */
  630.     pDrvCtrl->ilevel = ilevel; /* interrupt level */
  631.     pDrvCtrl->devAdrs = devAdrs; /* device I/O address */
  632.     pDrvCtrl->pciMemBase  = pciMemBase; /* pci memory base */
  633.     pDrvCtrl->memWidth  = memWidth; /* memory width */
  634.     pDrvCtrl->dcOpMode = (dcOpMode == NONE) ? 0 : dcOpMode; /* operation mode */
  635.     /* Publish the interface data record */
  636. #ifdef BSD43_DRIVER
  637.     ether_attach (
  638.   & pDrvCtrl->idr.ac_if,
  639.   unit,
  640.   "dc",
  641.   (FUNCPTR) NULL,
  642.   (FUNCPTR) dcIoctl,
  643.   (FUNCPTR) dcOutput,
  644.   (FUNCPTR) dcReset
  645.  );
  646. #else
  647.     ether_attach (
  648.                  (IFNET *) &pDrvCtrl->idr,
  649.                  unit,
  650.                  "dc",
  651.                  (FUNCPTR) NULL,
  652.                  (FUNCPTR) dcIoctl,
  653.                  (FUNCPTR) ether_output,
  654.                  (FUNCPTR) dcReset
  655.                  );
  656.      pDrvCtrl->idr.ac_if.if_start = (FUNCPTR) dcStartOutput;
  657. #endif /* BSD43_DRIVER */
  658. #ifdef DC_DEBUG
  659.     bzero ((char *)&pDrvCtrl->errStats, sizeof (DC_STATS));
  660. #endif /* DC_DEBUG */
  661.     dcInit(pDrvCtrl->devAdrs);
  662.     /* Create the transmit semaphore. */
  663.     if ((pDrvCtrl->TxSem = semMCreate (SEM_Q_PRIORITY | SEM_DELETE_SAFE |
  664.        SEM_INVERSION_SAFE)) == NULL)
  665.         {
  666.         printf ("dc: error creating transmitter semaphoren");
  667.         return (ERROR);
  668.         }
  669.     /* Establish size of shared memory region we require */
  670.     if ((int) memAdrs != NONE)  /* specified memory pool */
  671. {
  672. sz  = ((memSize - FLTR_FRM_SIZE + RMD_SIZ + TMD_SIZ) /
  673.                ((3 * DC_BUFSIZ) + RMD_SIZ + TMD_SIZ));
  674. dcNumRds = max (sz, MIN_RDS);
  675. dcNumTds = max (sz, MIN_TDS);
  676.         dcLPool = min (dcNumRds, DC_L_POOL);
  677. }
  678.     /* add it all up - allow for alignment adjustment */
  679.     sz = ((dcNumRds + 1) * RMD_SIZ) + (dcNumRds * DC_BUFSIZ) +
  680.  ((dcNumTds + 1) * TMD_SIZ) + (dcNumTds * DC_BUFSIZ) + 
  681.  (DC_BUFSIZ * dcLPool) + FLTR_FRM_SIZE;
  682.     /* Establish a region of shared memory */
  683.     /*
  684.      * OK. We now know how much shared memory we need.  If the caller
  685.      * provides a specific memory region, we check to see if the provided
  686.      * region is large enough for our needs.  If the caller did not
  687.      * provide a specific region, then we attempt to allocate the memory
  688.      * from the system, using the cache aware allocation system call.
  689.      */
  690.     switch ((int) memAdrs)
  691.         {
  692.         default :       /* caller provided memory */
  693.             if (memSize < sz)     /* not enough space */
  694.                 {
  695.                 printf ("dc: not enough memory providedn");
  696.                 return (ERROR);
  697.                 }
  698.             else
  699.                 dcNumRds += (memSize - sz) / (DC_BUFSIZ + TMD_SIZ);
  700.             pShMem = memAdrs;             /* set the beginning of pool */
  701.             /* assume pool is cache coherent, copy null structure */
  702.             pDrvCtrl->cacheFuncs = cacheNullFuncs;
  703.             break;
  704.         case NONE :     /* get our own memory */
  705.             /*
  706.      * Because the structures that are shared between the device
  707.              * and the driver may share cache lines, the possibility exists
  708.              * that the driver could flush a cache line for a structure and
  709.              * wipe out an asynchronous change by the device to a neighboring
  710.              * structure. Therefore, this driver cannot operate with memory
  711.              * that is not write coherent.  We check for the availability of
  712.              * such memory here, and abort if the system did not give us what
  713.              * we need.
  714.              */
  715.             if (!CACHE_DMA_IS_WRITE_COHERENT ())
  716.                 {
  717.                 printf ("dc: device requires cache coherent memoryn");
  718.                 return (ERROR);
  719.                 }
  720.             pShMem = (char *) cacheDmaMalloc (sz);
  721.             if ((int)pShMem == NULL)
  722.                 {
  723.                 printf ("dc: system memory unavailablen");
  724.                 return (ERROR);
  725.                 }
  726.             /* copy the DMA structure */
  727.             pDrvCtrl->cacheFuncs = cacheDmaFuncs;
  728.             break;
  729.         }
  730.     SYS_INT_CONNECT(pDrvCtrl, dcInt, pDrvCtrl, &retVal);
  731.     if (retVal == ERROR)
  732.         return (ERROR);
  733.     /*           Turkey Carving
  734.      *           --------------
  735.      *
  736.      *             LOW MEMORY
  737.      * |-------------------------------------|
  738.      * |         The Rx descriptors          |
  739.      * | (dcNumRds * sizeof (DC_RDE))        |
  740.      * |-------------------------------------|
  741.      * |          The receive buffers        |
  742.      * |       (DC_BUFSIZ * dcNumRds)        |
  743.      * |-------------------------------------|
  744.      * |         The Rx loaner pool          |
  745.      * |        (DC_BUFSIZ * dcLPool)        |
  746.      * |-------------------------------------|
  747.      * |         The Tx descriptors          |
  748.      * | (dcNumTds *  sizeof (DC_TDE))       |
  749.      * |-------------------------------------|
  750.      * |           The transmit buffers      |
  751.      * |       (DC_BUFSIZ * dcNumTds)        |
  752.      * |-------------------------------------|
  753.      * |           Setup Filter Frame        |
  754.      * |           (FLTR_FRM_SIZE)           |
  755.      * |-------------------------------------|
  756.      */
  757.     /* zero the shared memory */
  758.     bzero ( (char *) pShMem, (int) sz );
  759.     /* carve Rx memory structure */
  760.     pDrvCtrl->rxRing = (DC_RDE *) (((int)pShMem + 0x03) & ~0x03); /* wd align */
  761.     pDrvCtrl->dcNumRds = dcNumRds; /* receive ring size */
  762.     pDrvCtrl->rxIndex = 0;
  763.     /* Set up the Rx descriptors */
  764.     rmd = pDrvCtrl->rxRing;                      /* receive ring */
  765.     buf = (char *)(rmd + pDrvCtrl->dcNumRds);
  766.     for (ix = 0; ix < pDrvCtrl->dcNumRds; ix++, rmd++, buf += DC_BUFSIZ)
  767.         {
  768.         pTemp = DC_CACHE_VIRT_TO_PHYS (buf); /* convert to PCI  phys addr */
  769. pTemp = (void *)(MEM_TO_PCI_PHYS((ULONG)pTemp));
  770. rmd->rDesc2 = PCISWAP((ULONG)pTemp); /* buffer address 1 */
  771. rmd->rDesc3 = 0; /* no second buffer */
  772. /* buffer size */
  773. rmd->rDesc1 = PCISWAP(RDESC1_RBS1_VAL(DC_BUFSIZ) | 
  774.       RDESC1_RBS2_VAL(0));
  775. if (ix == (pDrvCtrl->dcNumRds - 1)) /* if its is last one */
  776.          rmd->rDesc1 |= PCISWAP(RDESC1_RER); /* end of receive ring */
  777. rmd->rDesc0 = PCISWAP(RDESC0_OWN); /* give ownership to lance */
  778.         }
  779.     /* setup Rx loaner pool */
  780.     pDrvCtrl->nLoanRx = dcLPool;
  781.     for (ix = 0; ix < dcLPool; ix++, buf += DC_BUFSIZ)
  782. {
  783.         pDrvCtrl->lPool[ix] = buf;
  784.         pDrvCtrl->refCnt[ix] = 0;
  785.         pDrvCtrl->pRefCnt[ix] = & pDrvCtrl->refCnt[ix];
  786. }
  787.     /* carve Tx memory structure */
  788.     pDrvCtrl->txRing = (DC_TDE *) (((int)buf + 0x03) & ~0x03); /* word align */
  789.     pDrvCtrl->dcNumTds = dcNumTds; /* transmit ring size */
  790.     pDrvCtrl->txIndex = 0;
  791.     pDrvCtrl->txDiIndex = 0;
  792.     /* Setup the Tx descriptors */
  793.     tmd = pDrvCtrl->txRing;                 /* transmit ring */
  794.     buf = (char *)(tmd + pDrvCtrl->dcNumTds);
  795.     for (ix = 0; ix < pDrvCtrl->dcNumTds; ix++, tmd++, buf += DC_BUFSIZ)
  796.         {
  797.         pTemp = DC_CACHE_VIRT_TO_PHYS (buf); /* convert to PCI phys addr */
  798. pTemp = (void *)(MEM_TO_PCI_PHYS((ULONG)pTemp));
  799. tmd->tDesc2 = PCISWAP((ULONG)pTemp); /* buffer address 1 */
  800. tmd->tDesc3 = 0; /* no second buffer */
  801. tmd->tDesc1 = PCISWAP((TDESC1_TBS1_PUT(0) |
  802.        TDESC1_TBS2_PUT(0) |
  803.        TDESC1_IC   |  /* intrpt on xmit */
  804.        TDESC1_LS          | /* last segment */
  805.        TDESC1_FS)); /* first segment */
  806. if (ix == (pDrvCtrl->dcNumTds - 1)) /* if its is last one */
  807.     tmd->tDesc1 |= PCISWAP(TDESC1_TER); /* end of Xmit ring */
  808. tmd->tDesc0 = 0 ; /* clear status */
  809.         }
  810.     /* carve Setup Filter Frame buffer */
  811.     
  812.     pDrvCtrl->pFltrFrm = (ULONG *)(((int)buf + 0x03) & ~0x03); /* word align */
  813.     buf += FLTR_FRM_SIZE;
  814.     /* Flush the write pipe */
  815.     CACHE_PIPE_FLUSH ();
  816.     /* Device Initialization */
  817.     dcChipReset (pDrvCtrl); /* reset the chip */
  818.     pTemp = DC_CACHE_VIRT_TO_PHYS (pDrvCtrl->rxRing);
  819.     pTemp = (void *)(MEM_TO_PCI_PHYS((ULONG)pTemp));
  820.     DC_CSR_WRITE (devAdrs, CSR3, ((ULONG)pTemp)); /* recv descriptor */
  821.     pTemp = DC_CACHE_VIRT_TO_PHYS (pDrvCtrl->txRing);
  822.     pTemp = (void *)(MEM_TO_PCI_PHYS((ULONG)pTemp));
  823.     DC_CSR_WRITE (devAdrs, CSR4, ((ULONG)pTemp)); /* xmit descriptor */
  824.     /* get the ethernet address */
  825.     if (!DEC21140(pDrvCtrl->dcOpMode))
  826.      {
  827.         if (dcEnetAddrGet (devAdrs, (char *) pDrvCtrl->idr.ac_enaddr, 6) != OK)
  828.     logMsg ("dc: error reading ethernet romn", 0,0,0,0,0,0);
  829.      }
  830.     else
  831.      {
  832.         if (dc21140EnetAddrGet (devAdrs, (char *) pDrvCtrl->idr.ac_enaddr, 6) 
  833.     != OK)
  834.     logMsg ("dc21140: error reading ethernet romn", 0,0,0,0,0,0);
  835.      }
  836.     if (!DEC21140(pDrvCtrl->dcOpMode))
  837.      {
  838.         dc21040AuiTpInit (devAdrs); /* configure AUI or 10BASE-T */
  839. DC_CSR_WRITE (devAdrs, CSR6, 0x0);
  840.         pDrvCtrl->dcMediaBlocks.DontSwitch = 1;
  841.      }
  842.     else
  843.      {
  844. DC_CSR_WRITE (devAdrs, CSR6, 0x0);
  845.         dc21140AuiMiiInit (pDrvCtrl, devAdrs, uTemp);
  846.      }
  847.     if ((pDrvCtrl->dcOpMode & DC_FULLDUPLEX_FLAG) && 
  848. (pDrvCtrl->dcOpMode != NONE))
  849.         DC_CSR_UPDATE (devAdrs, CSR6, CSR6_FD);
  850.     /* clear the status register */
  851.     DC_CSR_WRITE (devAdrs, CSR5, 0xffffffff);
  852.     /* set the operating mode to start Xmitter only */
  853.     DC_CSR_UPDATE (devAdrs, CSR6, (CSR6_ST | CSR6_BIT25));
  854.     if ((pDrvCtrl->dcOpMode & DC_ILOOPB_FLAG) &&
  855. (pDrvCtrl->dcOpMode != NONE))
  856.         DC_CSR_UPDATE (devAdrs, CSR6, CSR6_OM_ILB);
  857.     else if ((pDrvCtrl->dcOpMode & DC_ELOOPB_FLAG) &&
  858.              (pDrvCtrl->dcOpMode != NONE))
  859.         DC_CSR_UPDATE (devAdrs, CSR6, CSR6_OM_ELB);
  860.     /* Xmit a Filter Setup Frame */
  861.     dcFltrFrmXmit (pDrvCtrl, (char *) pDrvCtrl->idr.ac_enaddr, 1);
  862.     /* start the receiver with multicast and promiscuous mode, if needed */
  863.     DC_CSR_UPDATE (devAdrs, CSR6,
  864.                    (CSR6_SR | 
  865.                     ((pDrvCtrl->dcOpMode & DC_MULTICAST_FLAG) ? CSR6_PM: 0) |
  866.                     ((pDrvCtrl->dcOpMode & DC_PROMISCUOUS_FLAG) ? CSR6_PR: 0)));
  867.     /* set up the interrupts */
  868.     if (!DEC21140(pDrvCtrl->dcOpMode))
  869.      DC_CSR_WRITE (devAdrs, CSR7, (
  870.        CSR7_NIM | /* normal interrupt mask */
  871.        CSR7_AIM | /* abnormal interrupt mask */
  872.        CSR7_SEM | /* system error mask */
  873.        CSR7_RIM | /* rcv  interrupt mask */
  874.        CSR7_RUM | /* rcv buff unavailable mask */
  875.        CSR7_TUM  /* xmit buff unavailble mask */
  876.        ));
  877.     else
  878.      DC_CSR_WRITE (devAdrs, CSR7, (
  879.        CSR7_NIM | /* normal interrupt mask */
  880.        CSR7_AIM | /* abnormal interrupt mask */
  881.        CSR7_SEM | /* system error mask */
  882.        CSR7_RIM | /* rcv  interrupt mask */
  883.        CSR7_RUM | /* rcv buff unavailable mask */
  884.        CSR7_TUM  /* xmit buff unavailble mask */
  885.        ));
  886.     SYS_INT_ENABLE (pDrvCtrl);
  887.     pDrvCtrl->idr.ac_if.if_flags |= ((IFF_UP | IFF_RUNNING | IFF_NOTRAILERS) | 
  888.                        ((dcOpMode & DC_PROMISCUOUS_FLAG) ? IFF_PROMISC : 0) | 
  889.                        ((dcOpMode & DC_MULTICAST_FLAG) ? IFF_ALLMULTI : 0));
  890.     /* Set our flag */
  891.     pDrvCtrl->attached = TRUE;
  892.     pDrvCtrl->txFlushScheduled = FALSE;
  893.     return (OK);
  894.     }
  895. /*******************************************************************************
  896. *
  897. * dcReset - reset the interface
  898. *
  899. * Mark interface as inactive & reset the chip
  900. */
  901. LOCAL void dcReset
  902.     (
  903.     int unit
  904.     )
  905.     {
  906.     DRV_CTRL *pDrvCtrl = & drvCtrl [unit];
  907.     pDrvCtrl->idr.ac_if.if_flags = 0;
  908.     dcChipReset (pDrvCtrl);                           /* reset device */
  909.     }
  910. /*******************************************************************************
  911. *
  912. * dcInt - handle controller interrupt
  913. *
  914. * This routine is called at interrupt level in response to an interrupt from
  915. * the controller.
  916. */
  917. LOCAL void dcInt
  918.     (
  919.     DRV_CTRL * pDrvCtrl /* pointer to device control struct */
  920.     )
  921.     {
  922.     ULONG stat; /* status register */
  923.     ULONG devAdrs; /* device address */
  924.     devAdrs = pDrvCtrl->devAdrs;
  925.     /* Read the device status register */
  926.     stat = DC_CSR_READ (devAdrs, CSR5);
  927.     /* clear the interrupts */
  928.     DC_CSR_WRITE (devAdrs, CSR5, stat);
  929.     stat &= DC_CSR_READ (devAdrs, CSR7);
  930.     /* If false interrupt, return. */
  931.     if ( ! (stat & (CSR5_NIS | CSR5_AIS)) ) 
  932.         return;
  933.     /* Check for system error */
  934.     if (stat & CSR5_SE)
  935.         {
  936.         ++pDrvCtrl->idr.ac_if.if_ierrors;
  937.     
  938.         /* restart chip on fatal error */
  939.         pDrvCtrl->idr.ac_if.if_flags &= ~(IFF_UP | IFF_RUNNING);
  940.     
  941.         netJobAdd ((FUNCPTR)dcRestart, pDrvCtrl->idr.ac_if.if_unit, 0,0,0,0);
  942.         }
  943.     
  944.     /* Have netTask handle any input packets */
  945.     if (stat & (CSR5_RI | CSR5_RU))
  946.         {
  947.         DC_INT_DISABLE (devAdrs, CSR7_RIM);
  948.         netJobAdd ((FUNCPTR)dcHandleRecvInt, (int)pDrvCtrl, 0, 0, 0, 0);
  949.         }
  950.     if ((stat & CSR5_TU) && pDrvCtrl->idr.ac_if.if_snd.ifq_len &&
  951.         (! pDrvCtrl->txFlushScheduled))
  952.         {
  953.         pDrvCtrl->txFlushScheduled = TRUE;
  954.         netJobAdd ((FUNCPTR) dcTxFlush, (int) pDrvCtrl, 0, 0, 0, 0);
  955.         }
  956.     return;
  957.     }
  958. /*******************************************************************************
  959. *
  960. * dcHandleRecvInt - task level interrupt service for input packets
  961. *
  962. * This routine is called at task level indirectly by the interrupt
  963. * service routine to do any message received processing.
  964. */
  965. LOCAL void dcHandleRecvInt
  966.     (
  967.     DRV_CTRL * pDrvCtrl /* pointer to device control struct */
  968.     )
  969.     {
  970.     DC_RDE * rmd; /* pointer to Rx ring descriptor */
  971.     while ((rmd = dcGetFullRMD (pDrvCtrl)) != NULL)
  972.         dcRecv (pDrvCtrl, rmd);
  973.     DC_INT_ENABLE (pDrvCtrl->devAdrs, CSR7_RIM);
  974.     while ((rmd = dcGetFullRMD (pDrvCtrl)) != NULL)
  975.         dcRecv (pDrvCtrl, rmd);
  976. #ifdef DC_DEBUG
  977.     pDrvCtrl->errStats.rxMissed += (DC_CSR_READ (pDrvCtrl->devAdrs, CSR8) &
  978.                                     (CSR8_MFO | CSR8_MFC_MSK));
  979. #endif /* DC_DEBUG */
  980.     return;
  981.     }
  982. /*******************************************************************************
  983. *
  984. * dcTxRingClean - cleans up the transmit ring
  985. *
  986. * This routine is called at task level in the context of dcOutput() or
  987. * tNetTask by dcTxFlush() to collect statistics, and mark "free" all
  988. * descriptors consumed by the device.
  989. */
  990. LOCAL void dcTxRingClean
  991.     (
  992.     DRV_CTRL *pDrvCtrl
  993.     )
  994.     {
  995.     DC_TDE *    tmd;            /* pointer to Xmit ring descriptor */
  996.     while (pDrvCtrl->txDiIndex != pDrvCtrl->txIndex)
  997.         {
  998.         /* disposal has not caught up */
  999.         tmd = pDrvCtrl->txRing + pDrvCtrl->txDiIndex;
  1000.         /* if the buffer is still owned by device, don't touch it */
  1001.         DC_CACHE_INVALIDATE (tmd, TMD_SIZ);
  1002.         if (tmd->tDesc0 & PCISWAP(TDESC0_OWN))
  1003.             break;
  1004.         /* now bump the tmd disposal index pointer around the ring */
  1005.         pDrvCtrl->txDiIndex = (pDrvCtrl->txDiIndex + 1) % pDrvCtrl->dcNumTds;
  1006.         pDrvCtrl->txCount--;
  1007. #ifdef DC_DEBUG
  1008.         {
  1009.         UINT tdesc0 = PCISWAP(tmd->tDesc0);
  1010.         DC_STATS * pErrStats = &pDrvCtrl->errStats;
  1011.         if (tdesc0 & TDESC0_TO)
  1012.             pErrStats->txJbrTmo++;
  1013.         if (tdesc0 & TDESC0_LO)
  1014.             pErrStats->txLostCarrier++;
  1015.         if (tdesc0 & TDESC0_NC)
  1016.             pErrStats->txNoCarrier++;
  1017.         if (tdesc0 & TDESC0_LC)
  1018.             pErrStats->txLateCollision++;
  1019.         if (tdesc0 & TDESC0_HF)
  1020.             pErrStats->txHeartBeatFail++;
  1021.         if (tdesc0 & TDESC0_LF)
  1022.             pErrStats->txLinkFail++;
  1023.         if (tdesc0 & TDESC0_UF)
  1024.             pErrStats->txUnderflow++;
  1025.         if (tdesc0 & TDESC0_DE)
  1026.             pErrStats->txDeferred++;
  1027.         }
  1028. #endif /* DC_DEBUG */
  1029.         /*
  1030.          * TDESC0_ES is an "OR" of LC, NC, UF, EC.
  1031.          * here for error conditions.
  1032.          */
  1033.         if (tmd->tDesc0 & PCISWAP(TDESC0_ES)) 
  1034.     {
  1035.             /* check for no carrier */
  1036. #if 0  /* HELP */
  1037.             if ((tmd->tDesc0 & PCISWAP(TDESC0_NC | TDESC0_LO | TDESC0_LF)) &&
  1038.                 (pDrvCtrl->dcMediaBlocks.DontSwitch == 0)) 
  1039. {
  1040. dcSelectMedia (pDrvCtrl);
  1041. return;
  1042. }
  1043.             pDrvCtrl->dcMediaBlocks.DontSwitch = 1;
  1044. #endif
  1045.             pDrvCtrl->idr.ac_if.if_oerrors++;     /* output error */
  1046.             pDrvCtrl->idr.ac_if.if_opackets--;
  1047.             /*
  1048.      * If error was due to excess collisions, bump the collision
  1049.              * counter.
  1050.              */
  1051.             if (tmd->tDesc0 & PCISWAP(TDESC0_EC)) 
  1052. pDrvCtrl->idr.ac_if.if_collisions += 16;
  1053.     /* bump the collision counter if late collision */
  1054.     if (tmd->tDesc0 & PCISWAP(TDESC0_LC)) 
  1055. pDrvCtrl->idr.ac_if.if_collisions++;
  1056.     /* check for no carrier */
  1057. #if 0 /* HELP */
  1058.     if (tmd->tDesc0 & PCISWAP(TDESC0_NC | TDESC0_LO | TDESC0_LF)) 
  1059. {
  1060. logMsg ("dc%d: no carriern",
  1061. pDrvCtrl->idr.ac_if.if_unit, 0,0,0,0,0);
  1062. dcSelectMedia (pDrvCtrl);
  1063. }
  1064. #endif
  1065.             /*
  1066.      * Restart chip on fatal errors.
  1067.              * The following code handles the situation where the transmitter
  1068.              * shuts down due to an underflow error.  This is a situation that
  1069.              * will occur if the DMA cannot keep up with the transmitter.
  1070.              * It will occur if the device is being held off from DMA access
  1071.              * for too long or due to significant memory latency.  DRAM
  1072.              * refresh or slow memory could influence this.  Many
  1073.              * implementation use a dedicated device buffer.  This can be
  1074.              * static RAM to eliminate refresh conflicts; or dual-port RAM
  1075.              * so that the device can have free run of this memory during its
  1076.              * DMA transfers.
  1077.              */
  1078.             if (tmd->tDesc0 & PCISWAP(TDESC0_UF))
  1079.                 {
  1080.                 pDrvCtrl->idr.ac_if.if_flags &= ~(IFF_UP | IFF_RUNNING);
  1081.                 netJobAdd ((FUNCPTR)dcRestart, pDrvCtrl->idr.ac_if.if_unit,
  1082.                            0,0,0,0 );
  1083.                 return;
  1084.                 }
  1085.             }
  1086. tmd->tDesc0 = 0; /* clear all error & stat stuff */
  1087.         }
  1088.     /* Flush the write pipe */
  1089.     CACHE_PIPE_FLUSH ();
  1090.     }
  1091. /*******************************************************************************
  1092. *
  1093. * dcGetFullRMD - get next received message RMD
  1094. *
  1095. * Returns ptr to next Rx desc to process, or NULL if none ready.
  1096. */
  1097. LOCAL DC_RDE * dcGetFullRMD
  1098.     (
  1099.     DRV_CTRL * pDrvCtrl /* pointer to device control struct */
  1100.     )
  1101.     {
  1102.     DC_RDE * rmd; /* pointer to Rx ring descriptor */
  1103.     /* Refuse to do anything if flags are down */
  1104.     if  (
  1105.         (pDrvCtrl->idr.ac_if.if_flags & (IFF_UP | IFF_RUNNING) ) !=
  1106.         (IFF_UP | IFF_RUNNING)
  1107.         )
  1108.         return ((DC_RDE *) NULL);
  1109.     rmd = pDrvCtrl->rxRing + pDrvCtrl->rxIndex;       /* form ptr to Rx desc */
  1110.     DC_CACHE_INVALIDATE (rmd, RMD_SIZ);
  1111.     if ((rmd->rDesc0 & PCISWAP(RDESC0_OWN)) == 0)
  1112.         return (rmd);
  1113.     else
  1114.         return ((DC_RDE *) NULL);
  1115.     }
  1116. /*******************************************************************************
  1117. *
  1118. * dcRecv - process the next incoming packet
  1119. *
  1120. */
  1121. LOCAL STATUS dcRecv
  1122.     (
  1123.     DRV_CTRL * pDrvCtrl, /* pointer to device control struct */
  1124.     DC_RDE * rmd /* pointer to Rx ring descriptor */
  1125.     )
  1126.     {
  1127.     ENET_HDR * pEnetHdr; /* pointer to ethernet header */
  1128.     MBUF * pMbuf = NULL; /* pointer to mbuf */
  1129.     u_long pPhys;
  1130.     UCHAR * pData; /* pointer to data */
  1131.     int len; /* length */
  1132.     USHORT ether_type; /* ether packet type */
  1133. #ifdef DC_DEBUG
  1134.     UINT32 rdesc0; /* desc0 status word */
  1135. #endif /* DC_DEBUG */
  1136. #ifdef DC_DEBUG
  1137.     rdesc0 = rmd->rDesc0;
  1138.     if (rdesc0 & PCISWAP(0x40000000))
  1139.         pDrvCtrl->errStats.rxFiltrErr++;
  1140.     
  1141.     if (rdesc0 & PCISWAP(0x00004000))
  1142.         pDrvCtrl->errStats.rxDescErr++;
  1143.         
  1144.     if  (rdesc0 & PCISWAP(RDESC0_RF))
  1145.         pDrvCtrl->errStats.rxRuntFrm++;
  1146.     if  (rdesc0 & PCISWAP(RDESC0_TL))
  1147.         pDrvCtrl->errStats.rxTooLong++;
  1148.     if  (rdesc0 & PCISWAP(RDESC0_CS))
  1149.         pDrvCtrl->errStats.rxCollision++;
  1150.     if  (rdesc0 & PCISWAP(0x00000008))
  1151.         pDrvCtrl->errStats.rxMiiErr++;
  1152.     if  (rdesc0 & PCISWAP(RDESC0_DB))
  1153.         pDrvCtrl->errStats.rxDribbleBit++;
  1154.     if  (rdesc0 & PCISWAP(RDESC0_CE))
  1155.         pDrvCtrl->errStats.rxCrcErr++;
  1156. #endif /* DC_DEBUG */
  1157.     /* Discard if we have errors */
  1158.     if  (rmd->rDesc0 & PCISWAP(RDESC0_ES))
  1159.         {
  1160.         ++pDrvCtrl->idr.ac_if.if_ierrors;       /* bump error stat */
  1161.         goto cleanRXD;
  1162.         }
  1163.     /* Process clean packets */
  1164.     ++pDrvCtrl->idr.ac_if.if_ipackets; /* bump statistic */
  1165.     len = RDESC0_FL_GET(PCISWAP(rmd->rDesc0)); /* frame length */
  1166.     len -= 4;  /* Frame length includes CRC in it so subtract it */
  1167.     /* Get pointer to packet */
  1168.     pEnetHdr = DC_CACHE_PHYS_TO_VIRT(PCI_TO_MEM_PHYS(PCISWAP(rmd->rDesc2)));
  1169.     DC_CACHE_INVALIDATE (pEnetHdr, len);   /* make the packet data coherent */
  1170.     /* call input hook if any */
  1171.     if ((etherInputHookRtn == NULL) || ((*etherInputHookRtn)
  1172.        (& pDrvCtrl->idr.ac_if, (char *) pEnetHdr, len)) == 0)
  1173.         {
  1174.         /* Adjust length to size of data only */
  1175.         len -= SIZEOF_ETHERHEADER;
  1176.         /* Get pointer to packet data */
  1177.         pData = ((u_char *) pEnetHdr) + SIZEOF_ETHERHEADER;
  1178.         ether_type = ntohs ( pEnetHdr->type );
  1179.         /* OK to loan out buffer ? -> build an mbuf cluster */
  1180.     
  1181. if ((pDrvCtrl->nLoanRx > 0) && (USE_CLUSTER (len))
  1182.     && (pMbuf = BUILD_CLUSTER (pDrvCtrl, pEnetHdr, pData, len)))
  1183.     {
  1184.             pPhys = (u_long) DC_CACHE_VIRT_TO_PHYS(MEM_TO_PCI_PHYS(
  1185.     (pDrvCtrl->lPool[--pDrvCtrl->nLoanRx])));
  1186.     rmd->rDesc2 = PCISWAP(pPhys);
  1187.     }
  1188.         else
  1189.             {
  1190.             if ((pMbuf = bcopy_to_mbufs (pData, len, 0, & pDrvCtrl->idr.ac_if,
  1191.                 pDrvCtrl->memWidth)) == NULL)
  1192. {
  1193.                 ++pDrvCtrl->idr.ac_if.if_ierrors; /* bump error stat */
  1194.                 goto cleanRXD;
  1195. }
  1196.             }
  1197.         /* send on up... */
  1198.         do_protocol_with_type (ether_type, pMbuf, &pDrvCtrl->idr, len);
  1199.         }
  1200.     /* Done with descriptor, clean up and give it to the device. */
  1201. cleanRXD:
  1202.     /* clear status bits and give ownership to device */
  1203.     rmd->rDesc0 = PCISWAP(RDESC0_OWN);
  1204.     /* Flush the write pipe */
  1205.     CACHE_PIPE_FLUSH ();
  1206.     /* Advance our management index */
  1207.     pDrvCtrl->rxIndex = (pDrvCtrl->rxIndex + 1) % pDrvCtrl->dcNumRds;
  1208.     return (OK);
  1209.     }
  1210. #ifdef BSD43_DRIVER
  1211. /*******************************************************************************
  1212. *
  1213. * dcOutput - driver output routine
  1214. *
  1215. * This routine is called by the stack to transmit an mbuf.
  1216. * This routine is called by the stack to transmit an mbuf.
  1217. */
  1218. LOCAL int dcOutput
  1219.     (
  1220.     IDR  * pIDR, /* pointer to interface data record */
  1221.     MBUF * pMbuf, /* pointer to mbuf */
  1222.     SOCK * pDest /* pointer to destination sock */
  1223.     )
  1224.     {
  1225.     int  unit = ((IFNET *)pIDR)->if_unit;
  1226.     DRV_CTRL * pDrvCtrl = &drvCtrl[unit];
  1227.     int errorVal;
  1228.     errorVal =  ether_output ((IFNET *)pIDR, pMbuf, pDest,
  1229.                                (FUNCPTR) dcStartOutput, pIDR);
  1230.     if ((errorVal == ENOBUFS) && !pDrvCtrl->txFlushScheduled)
  1231.         {
  1232. #ifdef DC_DEBUG
  1233.         pDrvCtrl->errStats.txDropped++;
  1234. #endif /* DC_DEBUG */
  1235.         dcTxFlush (pDrvCtrl);
  1236.         }
  1237.     
  1238.     return (errorVal);
  1239.     }
  1240. #endif /* BSD43_DRIVER */
  1241. /*******************************************************************************
  1242. *
  1243. * dcTxFlush - flush enqueued transmit buffers
  1244. *
  1245. */
  1246. LOCAL void dcTxFlush
  1247.     (
  1248.     DRV_CTRL * pDrvCtrl
  1249.     )
  1250.     {
  1251.     int retry;
  1252.     int delayCount;
  1253. #ifdef DC_DEBUG
  1254.     pDrvCtrl->errStats.txFlushCalled++;
  1255.     if (pDrvCtrl->idr.ac_if.if_snd.ifq_len)
  1256.         pDrvCtrl->errStats.txFlushNeeded++;
  1257. #endif /* DC_DEBUG */
  1258.     retry = DC_FLUSH_RETRIES;
  1259.     while (pDrvCtrl->idr.ac_if.if_snd.ifq_len && retry)
  1260.         {
  1261.         dcTxRingClean (pDrvCtrl);
  1262.         if (DC_TD_INDEX_NEXT(pDrvCtrl) != pDrvCtrl->txDiIndex)
  1263.             DC_START_OUTPUT (pDrvCtrl);
  1264.         else
  1265.             {
  1266.             for (delayCount=1000; delayCount--;)
  1267.                 ;
  1268.             retry--;
  1269.             }
  1270.         }
  1271. #ifdef DC_DEBUG
  1272.     if (pDrvCtrl->idr.ac_if.if_snd.ifq_len == 0)
  1273.         pDrvCtrl->errStats.txFlushDone++;
  1274. #endif /* DC_DEBUG */
  1275.     pDrvCtrl->txFlushScheduled = FALSE;
  1276.     }
  1277.     
  1278. /*******************************************************************************
  1279. *
  1280. * dcStartOutput - send transmit buffers
  1281. *
  1282. */
  1283. LOCAL void dcStartOutput
  1284.     (
  1285. #   ifdef BSD43_DRIVER
  1286.     int unit
  1287. #   else
  1288.     DRV_CTRL * pDrvCtrl
  1289. #   endif /* BSD43_DRIVER */
  1290.     )
  1291.     {
  1292. #   ifdef BSD43_DRIVER    
  1293.     DRV_CTRL * pDrvCtrl = &drvCtrl[unit];
  1294. #   endif /* BSD43_DRIVER */    
  1295.     DC_TDE * pTxD;
  1296.     MBUF * pMbuf;
  1297.     char *  pTxdBuf;
  1298.     int bufLen;
  1299.     int retries;
  1300. #ifdef DC_DEBUG
  1301.     pDrvCtrl->errStats.txQsizeCur=pDrvCtrl->idr.ac_if.if_snd.ifq_len;
  1302. #endif /* DC_DEBUG */
  1303.     retries = MAX_TX_RETRIES;
  1304.     while (pDrvCtrl->idr.ac_if.if_snd.ifq_len && retries)
  1305.         {
  1306.         pTxD = pDrvCtrl->txRing + pDrvCtrl->txIndex;
  1307.         if  (((pTxD->tDesc0 & PCISWAP(TDESC0_OWN)) != 0) ||
  1308.              (DC_TD_INDEX_NEXT (pDrvCtrl) == pDrvCtrl->txDiIndex))
  1309.             {
  1310.             dcTxRingClean (pDrvCtrl);
  1311. #ifdef DC_DEBUG
  1312.             pDrvCtrl->errStats.txRetries++;
  1313. #endif /* DC_DEBUG */
  1314.             retries--;
  1315.             continue;
  1316.             }
  1317.         retries = MAX_TX_RETRIES;
  1318.         
  1319.         /* Get pointer to transmit buffer */
  1320.         pTxdBuf = (char *)DC_CACHE_PHYS_TO_VIRT(PCI_TO_MEM_PHYS(
  1321.          PCISWAP(pTxD->tDesc2)));
  1322.         IF_DEQUEUE (&pDrvCtrl->idr.ac_if.if_snd, pMbuf);
  1323.         /* copy stuff */
  1324.         bcopy_from_mbufs (pTxdBuf, pMbuf, bufLen, pDrvCtrl->memWidth);
  1325.         pTxD->tDesc0  = 0; /* clear buffer error status */
  1326.         pTxD->tDesc1 &= PCISWAP (~TDESC1_TBS1_MSK);
  1327.         pTxD->tDesc1 |= PCISWAP (TDESC1_TBS1_PUT(max (ETHERSMALL, bufLen)));
  1328.         pTxD->tDesc0  = PCISWAP (TDESC0_OWN);  /* give ownership to device */
  1329.         CACHE_PIPE_FLUSH (); /* Flush the write pipe */
  1330.         /* Advance our management index */
  1331.         pDrvCtrl->txIndex = DC_TD_INDEX_NEXT (pDrvCtrl);
  1332.         /* Kickstart transmit */
  1333.     
  1334.         if (dcKickStartTx)
  1335.             DC_CSR_WRITE (pDrvCtrl->devAdrs, CSR1, CSR1_TPD);
  1336.         pDrvCtrl->txCount++;
  1337.         }
  1338.     /* Scrub the Tx ring */
  1339.     if (pDrvCtrl->txCount > (pDrvCtrl->dcNumTds/3))
  1340.         dcTxRingClean (pDrvCtrl);
  1341. #ifdef DC_DEBUG
  1342.     if (pDrvCtrl->errStats.txQsizeCur > pDrvCtrl->errStats.txQsizeMax)
  1343.         pDrvCtrl->errStats.txQsizeMax = pDrvCtrl->errStats.txQsizeCur;
  1344. #endif /* DC_DEBUG */
  1345.     }
  1346. /*******************************************************************************
  1347. *
  1348. * dcIoctl - the driver I/O control routine
  1349. *
  1350. * Process an ioctl request.
  1351. */
  1352. LOCAL int dcIoctl
  1353.     (
  1354.     IDR  * ifp, /* pointer interface data record */
  1355.     int cmd, /* command */
  1356.     caddr_t data /* data */
  1357.     )
  1358.     {
  1359.     int  error = 0;
  1360.     DRV_CTRL *  pDrvCtrl = (DRV_CTRL *)ifp; /* pointer to device */
  1361.     switch (cmd)
  1362.         {
  1363.         case SIOCSIFADDR:
  1364.             ifp->ac_ipaddr = IA_SIN (data)->sin_addr;
  1365.             break;
  1366.         case SIOCSIFFLAGS:
  1367.             /* No further work to be done */
  1368.             break;
  1369.         case IFF_PROMISC: /* set device in promiscuous mode */
  1370.     DC_CSR_UPDATE (pDrvCtrl->devAdrs, CSR6, CSR6_PR);
  1371.     break;
  1372.         default:
  1373.             error = EINVAL;
  1374.         }
  1375.     return (error);
  1376.     }
  1377. /*******************************************************************************
  1378. *
  1379. * dcChipReset - hardware reset of chip (stop it)
  1380. */
  1381. LOCAL int dcChipReset
  1382.     (
  1383.     DRV_CTRL * pDrvCtrl /* pointer to device control structure */
  1384.     )
  1385.     {
  1386.     ULONG   devAdrs = pDrvCtrl->devAdrs; /* device base address */
  1387.     ULONG ix; /* index */
  1388.     DC_CSR_WRITE (devAdrs, CSR6, 0); /* stop rcvr & xmitter */
  1389.     DC_CSR_WRITE (devAdrs, CSR7, 0); /* mask interrupts */
  1390.     
  1391.     DC_CSR_WRITE (devAdrs, CSR0, CSR0_SWR);
  1392.     /* Wait Loop, Loop for at least 50 PCI cycles according to chip spec */
  1393.     for (ix = 0; ix < 0x1000; ix++)
  1394. ;
  1395.     /* any additional bus mode | give xmit & rcv process equal priority */
  1396.     DC_CSR_WRITE (devAdrs, CSR0, (dcCSR0Bmr | CSR0_BAR | CSR0_RML |
  1397.                                 CSR0_CAL_32 | CSR0_PBL_32));
  1398.     for (ix = 0; ix < 0x1000; ix++) /* loop for some cycles */
  1399. ;
  1400.     return (OK);
  1401.     }
  1402. /*******************************************************************************
  1403. *
  1404. * dc21040AuiTpInit - initialize either AUI or 10BASE-T connection
  1405. *
  1406. * This function configures 10BASE-T interface. If the link pass state is 
  1407. * not achieved within two seconds then the AUI interface is initialized.
  1408. */
  1409. LOCAL void dc21040AuiTpInit
  1410.     (
  1411.     ULONG       devAdrs        /* device base I/O address */
  1412.     )
  1413.     {
  1414.     /* reset the SIA registers */
  1415.     DC_CSR_WRITE (devAdrs, CSR13, 0);
  1416.     DC_CSR_WRITE (devAdrs, CSR14, 0);
  1417.     DC_CSR_WRITE (devAdrs, CSR15, 0);
  1418.     /* configure for the 10BASE-T */
  1419.     DC_CSR_WRITE (devAdrs, CSR13, CSR13_CAC_CSR); /* 10BT auto configuration */
  1420.     taskDelay (sysClkRateGet() * 2); /* 2 second delay */
  1421.     if (DC_CSR_READ (devAdrs, CSR12) & (CSR12_LKF | CSR12_NCR))
  1422. {
  1423. /* 10BASE-T not connected initialize interface for AUI */
  1424. DC_CSR_WRITE (devAdrs, CSR13, 0); /* reset SIA registers */
  1425. DC_CSR_WRITE (devAdrs, CSR14, 0);
  1426. DC_CSR_WRITE (devAdrs, CSR15, 0);
  1427. /* AUI auto configuration */
  1428. DC_CSR_WRITE (devAdrs, CSR13, (CSR13_AUI_TP | CSR13_CAC_CSR));
  1429. }
  1430.     }
  1431. /*******************************************************************************
  1432. *
  1433. * dc21140SROMVersionGet - gets the SROM format version
  1434. *
  1435. * RETURNS: 0 - Undefined/Unknown; 1 - Version 1/A; 3 - Version 3.0
  1436. */
  1437. LOCAL UCHAR dc21140SROMVersionGet
  1438.     (
  1439.     ULONG devAdrs
  1440.     )
  1441.     {
  1442.     union SROMData
  1443. {
  1444.         char    Char[6];        /* temporary 6 x Char */
  1445.         USHORT  Short[2];       /* temporary USHORT */
  1446.         ULONG   Long;           /* temporay ULONG */
  1447.         } SROMData;
  1448.     /* Check if SROM is programmed. */
  1449.     SROMData.Short[0] = dcReadRom (devAdrs, 0);
  1450.     if (SROMData.Short[0] == 0xFFFF) 
  1451. {
  1452.         return (0);
  1453.      }
  1454.     SROMData.Short[0] = dcReadRom (devAdrs, 9);
  1455.     switch (SROMData.Char[1]) 
  1456. {
  1457.         case 1:
  1458.             return (1);
  1459.         case 3:
  1460.             return (3);
  1461.         default:
  1462.             break;
  1463.      }
  1464.     return (0);
  1465.     }
  1466. /*******************************************************************************
  1467. *
  1468. * dcSetDefaultMediaTypes - initialize Media info for blank SROMs.
  1469. *
  1470. *
  1471. */
  1472. LOCAL void dcSetDefaultMediaTypes
  1473.     (
  1474.     DRV_CTRL *pDrvCtrl
  1475.     ) 
  1476.     {
  1477.     pDrvCtrl->dcMediaBlocks.MediaFound = 3;
  1478.     pDrvCtrl->dcMediaBlocks.ActiveMedia = 0;
  1479.     pDrvCtrl->dcMediaBlocks.GPMask = 0x60;
  1480.     /* AUI */
  1481.     pDrvCtrl->dcMediaBlocks.MediaArray[0].ValCSR6 = CSR6_BIT25;
  1482.     pDrvCtrl->dcMediaBlocks.MediaArray[0].GPCount = 0;
  1483.     /* 10BaseT */
  1484.     pDrvCtrl->dcMediaBlocks.MediaArray[1].ValCSR6 = CSR6_PS | CSR6_BIT25;
  1485.     pDrvCtrl->dcMediaBlocks.MediaArray[1].GPCount = 1;
  1486.     pDrvCtrl->dcMediaBlocks.MediaArray[2].GPValue[0] = 0x40;
  1487.     /* 100BaseT4 */
  1488.     pDrvCtrl->dcMediaBlocks.MediaArray[2].ValCSR6 = CSR6_PS | CSR6_BIT25;
  1489.     pDrvCtrl->dcMediaBlocks.MediaArray[2].GPCount = 1;
  1490.     pDrvCtrl->dcMediaBlocks.MediaArray[2].GPValue[0] = 0x40;
  1491.     }
  1492. /*******************************************************************************
  1493. *
  1494. * dcDoCompactInfo - initialize Compact Media info for Version 3.0 SROMs.
  1495. *
  1496. */
  1497. LOCAL void dcDoCompactInfo 
  1498.     (
  1499.     DRV_CTRL *pDrvCtrl, 
  1500.     CompactFormat *pCompactData, 
  1501.     UINT *pCSR6, UINT MediaUnit
  1502.     )
  1503.     {
  1504.     pDrvCtrl->dcMediaBlocks.MediaArray[MediaUnit].GPCount = 1;
  1505.     pDrvCtrl->dcMediaBlocks.MediaArray[MediaUnit].GPValue[0] = 
  1506.      pCompactData->GPPortData;
  1507.     if (pCompactData->Command & 1)
  1508. *pCSR6 |= CSR6_PS;
  1509.     if (pCompactData->Command & 10)
  1510. *pCSR6 |= CSR6_TTM;
  1511.     if (pCompactData->Command & 20)
  1512. *pCSR6 |= CSR6_PCS;
  1513.     if (pCompactData->Command & 40)
  1514. *pCSR6 |= CSR6_SCR;
  1515.     return;
  1516.     }
  1517. /*******************************************************************************
  1518. *
  1519. * dc21140AuiMiiInit - initialize either AUI or MII connection
  1520. *
  1521. * This function configures 21140.  The SROM is used to set the chipset
  1522. * (DEC21140/PHY) if the SROM is configured.  The settings are tried and
  1523. * if there is no errors (link fail, no carrier, ...) the configuration
  1524. * is used.  If an error occurs, the next media info leaf is tried, etc.
  1525. * If the SROM is not programmed, or contains invalid data, a "generic"
  1526. * TP setting is used/tried and, if failure, the AUI port is used.
  1527. */
  1528. LOCAL void dc21140AuiMiiInit
  1529.     (
  1530.     DRV_CTRL *pDrvCtrl,
  1531.     ULONG devAdrs, 
  1532.     UINT dcCSR6
  1533.     )
  1534.     {
  1535.     union SROMData 
  1536. {
  1537.         char    Char[6];        /* temporary 6 x Char */
  1538.         USHORT  Short[2];       /* temporary USHORT */
  1539.         ULONG   Long;           /* temporay ULONG */
  1540.      } SROMData;
  1541.     UINT BlockCount = 0, 
  1542.          GPRLength  = 0,
  1543.          OldCSR6    = 0, 
  1544.          ii, jj;
  1545.     UCHAR *pTmp;
  1546.     InfoLeaf *dcInfoLeaf;
  1547.     InfoBlock *pInfoBlock;
  1548.     UCHAR SROMBuffer [128];
  1549.     pDrvCtrl->dcMediaBlocks.DontSwitch = 0;
  1550.     dcCSR6 = dcCSR6 | CSR6_BIT25;
  1551.     OldCSR6 = dcCSR6;
  1552.     /* Get SROM version */
  1553.     switch (dc21140SROMVersionGet (devAdrs)) 
  1554. {
  1555. /* Valid Version 3 format was found, try info leafs. */
  1556. case 3: 
  1557.     for ( ii = 0; ii < 64; ii++ ) 
  1558. {
  1559. SROMData.Short[0] = dcReadRom (devAdrs, ii);
  1560. SROMBuffer [ii*2] = SROMData.Char[1];
  1561. SROMBuffer [(ii*2)+1] = SROMData.Char[0];
  1562. }
  1563.     dcInfoLeaf = (InfoLeaf *)(&(SROMBuffer[SROMBuffer[27]])); 
  1564.     BlockCount = dcInfoLeaf->BlockCount;
  1565.     pInfoBlock = &dcInfoLeaf->dcInfoBlock;
  1566.     pDrvCtrl->dcMediaBlocks.MediaFound = BlockCount;
  1567.     pDrvCtrl->dcMediaBlocks.GPMask = dcInfoLeaf->GPControl;  
  1568.     for (ii = 0; ii < BlockCount; ii++) 
  1569. {
  1570. pTmp =  (UCHAR *)pInfoBlock;
  1571. if ( !(pInfoBlock->Compact.MediaCode & 0x80) ) 
  1572.     {
  1573.     /* Compact Format */
  1574.                     pDrvCtrl->dcMediaBlocks.MediaArray[0].GPCount = 0;
  1575.     dcDoCompactInfo(pDrvCtrl, &(pInfoBlock->Compact), 
  1576.     &dcCSR6, ii);
  1577.     pDrvCtrl->dcMediaBlocks.MediaArray[ii].ValCSR6 = dcCSR6;
  1578.     pTmp = &(pTmp[4]);
  1579.     }
  1580. else 
  1581.     {
  1582.     /* Extended Format */
  1583.     if (pInfoBlock->Extended0.Type) 
  1584. {
  1585. /* Block Type 1 */
  1586. dcCSR6 = dcCSR6 | CSR6_BIT25 | CSR6_PS;
  1587. /* Get General Purpose Data. */
  1588. GPRLength = pInfoBlock->Extended1.BlockData[1];
  1589. pDrvCtrl->dcMediaBlocks.MediaArray[ii].GPCount =
  1590. GPRLength;
  1591. for (jj = 0; jj < GPRLength; jj++) 
  1592.     {
  1593.     pDrvCtrl->dcMediaBlocks.MediaArray[ii].GPValue[jj] =
  1594.      pInfoBlock->Extended1.BlockData[jj+2];
  1595.     }
  1596. pDrvCtrl->dcMediaBlocks.MediaArray[ii].GPResetLen = 
  1597. pInfoBlock->Extended1.BlockData[GPRLength+2];
  1598. for (jj = 0; 
  1599.      jj < pDrvCtrl->dcMediaBlocks.MediaArray[ii].
  1600. GPResetLen; jj++) 
  1601.     {
  1602.     pDrvCtrl->dcMediaBlocks.MediaArray[ii].
  1603.      GPResetValue[jj] = 
  1604.      pInfoBlock->Extended1.
  1605.      BlockData[GPRLength+jj+3];
  1606.     }
  1607. }
  1608.     else 
  1609. {
  1610. /* Block Type 0 */
  1611. dcCSR6 = dcCSR6 | CSR6_TTM | CSR6_BIT25;
  1612. dcDoCompactInfo (pDrvCtrl,
  1613. (CompactFormat *)
  1614.     (pInfoBlock->Extended1.BlockData), 
  1615. &dcCSR6, ii);
  1616. }
  1617. pDrvCtrl->dcMediaBlocks.MediaArray[ii].ValCSR6 = dcCSR6;
  1618. pTmp = &(pTmp[(pInfoBlock->Extended0.Length & ~0x80)
  1619. + 1]);
  1620.     }
  1621. pDrvCtrl->dcMediaBlocks.ActiveMedia = 0;
  1622. dcCSR6 = OldCSR6;
  1623. pInfoBlock = (InfoBlock *)pTmp;
  1624. }
  1625.     pDrvCtrl->dcMediaBlocks.ActiveMedia = BlockCount - 1;
  1626.     dcSelectMedia (pDrvCtrl);
  1627.     break;
  1628. default:
  1629.     /* Invalid format was found, try MII then AUI. */
  1630.     dcSetDefaultMediaTypes (pDrvCtrl);
  1631.     pDrvCtrl->dcMediaBlocks.ActiveMedia = 1;
  1632.     dcSelectMedia (pDrvCtrl);
  1633.     break;
  1634. }
  1635.     return;
  1636.     }
  1637. /*******************************************************************************
  1638. *
  1639. * dcMiiPhyRead - read a PHY device register via MII
  1640. *
  1641. * RETURNS: the contents of a PHY device register.
  1642. */
  1643. LOCAL USHORT dcMiiPhyRead
  1644.     (
  1645.     DRV_CTRL *pDrvCtrl,
  1646.     UINT phyAdrs,                     /* PHY address to access */
  1647.     UINT phyReg                       /* PHY register to read */
  1648.     )
  1649.     {
  1650.     USHORT retVal=0;
  1651.     
  1652.     /* Write 34-bit preamble */
  1653.     DC_MII_WRITE (pDrvCtrl->devAdrs, MII_PREAMBLE, 32);
  1654.     DC_MII_WRITE (pDrvCtrl->devAdrs, MII_PREAMBLE, 2);
  1655.     /* start of frame + op-code nibble */
  1656.     DC_MII_WRITE (pDrvCtrl->devAdrs, MII_SOF | MII_RD, 4);
  1657.     /* device address */
  1658.     DC_MII_WRITE (pDrvCtrl->devAdrs, phyAdrs, 5);
  1659.     DC_MII_WRITE (pDrvCtrl->devAdrs, phyReg, 5);
  1660.     /* turn around */
  1661.     DC_MII_RTRISTATE (pDrvCtrl->devAdrs);
  1662.     /* read data */
  1663.     DC_MII_READ (pDrvCtrl->devAdrs, &retVal, 16);
  1664.     return (retVal);
  1665.     }
  1666. /*******************************************************************************
  1667. *
  1668. * dcMiiPhyWrite - write to a PHY device register via MII
  1669. *
  1670. * RETURNS: none
  1671. */
  1672. LOCAL void dcMiiPhyWrite
  1673.     (
  1674.     DRV_CTRL *pDrvCtrl,
  1675.     UINT phyAdrs,                     /* PHY address to access */
  1676.     UINT phyReg,                      /* PHY register to write */
  1677.     USHORT data                         /* Data to write */
  1678.     )
  1679.     {
  1680.     /* write 34-bit preamble */
  1681.     DC_MII_WRITE (pDrvCtrl->devAdrs, MII_PREAMBLE, 32);
  1682.     DC_MII_WRITE (pDrvCtrl->devAdrs, MII_PREAMBLE, 2);
  1683.     /* start of frame + op-code nibble */
  1684.     DC_MII_WRITE (pDrvCtrl->devAdrs, MII_SOF | MII_WR, 4);
  1685.     /* device address */
  1686.     DC_MII_WRITE (pDrvCtrl->devAdrs, phyAdrs, 5);
  1687.     DC_MII_WRITE (pDrvCtrl->devAdrs, phyReg, 5);
  1688.     /* turn around */
  1689.     DC_MII_WTRISTATE (pDrvCtrl->devAdrs);
  1690.     /* write data */
  1691.     DC_MII_WRITE (pDrvCtrl->devAdrs, data, 16);
  1692.     }
  1693. /*******************************************************************************
  1694. *
  1695. * dcSelectMedia - select the next media type supported.
  1696. *
  1697. * RETURNS: none
  1698. */
  1699. LOCAL void dcSelectMedia 
  1700.     (
  1701.     DRV_CTRL *pDrvCtrl
  1702.     )
  1703.     {
  1704.     UINT csr6val;
  1705.     UINT csr7val;
  1706.     UINT jj;
  1707.     UINT ix;
  1708.     UINT phyAddr;
  1709.     USHORT miiData;
  1710.     UINT linkTry = 0;
  1711.     if (pDrvCtrl->dcMediaBlocks.DontSwitch) 
  1712.      {
  1713.      return;
  1714.      }
  1715.     csr6val = DC_CSR_READ (pDrvCtrl->devAdrs, CSR6);
  1716.     csr7val = DC_CSR_READ (pDrvCtrl->devAdrs, CSR7); /* save CSR7 */
  1717.     /* Stop Receive/Transmit Processes */
  1718.     DC_CSR_WRITE (pDrvCtrl->devAdrs, CSR6, (~(CSR6_ST|CSR6_SR) & csr6val)); 
  1719.     taskDelay (sysClkRateGet() * 1);
  1720.     if(pDrvCtrl->dcMediaBlocks.MediaArray[pDrvCtrl->
  1721. dcMediaBlocks.ActiveMedia].GPCount) 
  1722. {
  1723. for (jj=0; jj < pDrvCtrl->dcMediaBlocks.
  1724.     MediaArray[pDrvCtrl->dcMediaBlocks.ActiveMedia].GPResetLen; jj++) 
  1725.     {
  1726.     DC_CSR_WRITE (pDrvCtrl->devAdrs, CSR12,
  1727. pDrvCtrl->dcMediaBlocks.
  1728. MediaArray[pDrvCtrl->dcMediaBlocks.ActiveMedia].
  1729. GPResetValue[jj]);
  1730.     DC_CSR_WRITE (pDrvCtrl->devAdrs, CSR12, 
  1731. pDrvCtrl->dcMediaBlocks.GPMask | 0x100);
  1732.     for (ix = 0; ix < 0x1000; ix++)
  1733. ;
  1734.     }
  1735. for (jj=0; jj < pDrvCtrl->dcMediaBlocks.
  1736.     MediaArray[pDrvCtrl->dcMediaBlocks.
  1737.     ActiveMedia].GPCount; jj++) 
  1738.     {
  1739.     DC_CSR_WRITE (pDrvCtrl->devAdrs, CSR12,
  1740. pDrvCtrl->dcMediaBlocks.
  1741. MediaArray[pDrvCtrl->
  1742. dcMediaBlocks.
  1743. ActiveMedia].
  1744. GPValue [jj]);
  1745.     DC_CSR_WRITE (pDrvCtrl->devAdrs, CSR12, 
  1746. pDrvCtrl->dcMediaBlocks.GPMask | 0x100);
  1747.     for (ix = 0; ix < 0x1000; ix++)
  1748. ;
  1749.     }
  1750.         
  1751.             /* Find first PHY attached to DEC21140 */
  1752.             for (phyAddr = 0; phyAddr < DC_MAX_PHY; phyAddr++) 
  1753.                 {
  1754.                 miiData = dcMiiPhyRead(pDrvCtrl, phyAddr, MII_PHY_ID0);
  1755.                 if (miiData != 0xFFFF) /* Found PHY */
  1756.                     break;
  1757.                 }
  1758.             if (miiData != 0xFFFF)
  1759.                 {
  1760.                 linkTry=0;
  1761.                 miiData=0;
  1762.                 while ( !(miiData & MII_PHY_SR_LNK) &&
  1763.                         (linkTry < DC_MAX_LINK_TOUT))
  1764.                     {
  1765.                     taskDelay (sysClkRateGet() * 1); /* 1 second delay */
  1766.                     miiData = dcMiiPhyRead(pDrvCtrl, phyAddr, MII_PHY_SR);
  1767.                     linkTry++;
  1768.                     }
  1769.                 if (linkTry >= DC_MAX_LINK_TOUT)
  1770.                     {
  1771.                     /* Setup next media to try */
  1772.                     
  1773.                     if ((pDrvCtrl->dcMediaBlocks.ActiveMedia >= 
  1774.                 pDrvCtrl->dcMediaBlocks.MediaFound) ||
  1775.                 (pDrvCtrl->dcMediaBlocks.ActiveMedia == 0))
  1776.                         {
  1777.                         /*
  1778.                          * This is the last media supported.
  1779.                          * Leave chip programmed this way.
  1780.                          */
  1781.                 pDrvCtrl->dcMediaBlocks.DontSwitch = 1;
  1782.                         }
  1783.                     else
  1784.                         {
  1785.                         /* Attempt next media type */
  1786.                         
  1787.                         pDrvCtrl->dcMediaBlocks.ActiveMedia -= 1;
  1788.         dcSelectMedia (pDrvCtrl);
  1789.                         return;
  1790.                         }
  1791.                     }
  1792.                 }
  1793.             else /* don't know PHY type, delay 2 seconds */
  1794.                 {
  1795.                 taskDelay (sysClkRateGet() * 2); /* 2 second delay */
  1796.                 }
  1797.          }
  1798.     /*
  1799.      * Set Capture Effect Enable and Transmit Threshold to 160 by
  1800.      * default.
  1801.      */
  1802.     DC_CSR_WRITE (pDrvCtrl->devAdrs, CSR6, pDrvCtrl->dcMediaBlocks.
  1803. MediaArray[pDrvCtrl->dcMediaBlocks.ActiveMedia].ValCSR6 | 
  1804. CSR6_THR_160 | CSR6_BIT25 | CSR6_CAE | 0x80000000);
  1805.     DC_CSR_WRITE (pDrvCtrl->devAdrs, CSR0, 
  1806.         DC_CSR_READ (pDrvCtrl->devAdrs, CSR0) | CSR0_SWR);
  1807.     taskDelay (sysClkRateGet() * 1); /* 1 second delay */
  1808.     DC_CSR_WRITE (pDrvCtrl->devAdrs, CSR0, 
  1809.         CSR0_BAR | CSR0_RML | CSR0_CAL_32 | CSR0_PBL_32);
  1810.     /*
  1811.      * Set Capture Effect Enable and Transmit Threshold to 160 by
  1812.      * default.
  1813.      */
  1814.     DC_CSR_WRITE (pDrvCtrl->devAdrs, CSR6, pDrvCtrl->dcMediaBlocks.
  1815. MediaArray[pDrvCtrl->dcMediaBlocks.ActiveMedia].ValCSR6 | 
  1816. CSR6_THR_160 | CSR6_BIT25 | CSR6_CAE | 0x80000000);
  1817.     DC_CSR_WRITE (pDrvCtrl->devAdrs, CSR7, csr7val);  /* restore CSR7 */
  1818.     /* Restore transmit and receiver process */
  1819.     csr6val &= (CSR6_SR | CSR6_ST);
  1820.     csr6val |= DC_CSR_READ (pDrvCtrl->devAdrs, CSR6);
  1821.     DC_CSR_WRITE (pDrvCtrl->devAdrs, CSR6, csr6val);
  1822.     /* Setup next media to try */
  1823.     if ((pDrvCtrl->dcMediaBlocks.ActiveMedia >= 
  1824. pDrvCtrl->dcMediaBlocks.MediaFound) ||
  1825. (pDrvCtrl->dcMediaBlocks.ActiveMedia == 0))
  1826. pDrvCtrl->dcMediaBlocks.DontSwitch = 1;
  1827.     pDrvCtrl->dcMediaBlocks.ActiveMedia -= 1;
  1828.     return;
  1829.     }
  1830. /*******************************************************************************
  1831. *
  1832. * dcCsrWrite - select and write a CSR register
  1833. *
  1834. */
  1835. LOCAL void dcCsrWrite
  1836.     (
  1837.     ULONG  devAdrs, /* device address base */
  1838.     int  reg, /* register to select */
  1839.     ULONG  value /* value to write */
  1840.     )
  1841.     {
  1842.     ULONG * csrReg;
  1843.     csrReg = (ULONG *)(devAdrs + (reg * DECPCI_REG_OFFSET));
  1844.     /* write val to CSR */
  1845.     *(csrReg) = PCISWAP(value);
  1846.     }
  1847. /*******************************************************************************
  1848. *
  1849. * dcCsrRead - select and read a CSR register
  1850. *
  1851. */
  1852. LOCAL ULONG dcCsrRead
  1853.     (
  1854.     ULONG devAdrs, /* device address base */
  1855.     int reg /* register to select */
  1856.     )
  1857.     {
  1858.     ULONG * csrReg; /* csr register */
  1859.     ULONG csrData; /* data in csr register */
  1860.     csrReg = (ULONG *)(devAdrs + (reg * DECPCI_REG_OFFSET));
  1861.     csrData = *csrReg;
  1862.     /* get contents of CSR */
  1863.     return (PCISWAP(csrData));
  1864.     }
  1865. /*******************************************************************************
  1866. *
  1867. * dcRestart - restart the device after a fatal error
  1868. *
  1869. * This routine takes care of all the messy details of a restart.  The device
  1870. * is reset and re-initialized.  The driver state is re-synchronized.
  1871. */
  1872. LOCAL void dcRestart
  1873.     (
  1874.     int  unit /* unit to restart */
  1875.     )
  1876.     {
  1877.     ULONG status; /* status register */
  1878.     int ix; /* index variable */
  1879.     DC_RDE * rmd; /* pointer to receive descriptor */
  1880.     DC_TDE * tmd; /* pointer to Xmit descriptor */
  1881.     DRV_CTRL * pDrvCtrl = & drvCtrl [unit];
  1882.     rmd = pDrvCtrl->rxRing;      /* receive ring */
  1883.     tmd = pDrvCtrl->txRing;      /* transmit ring */
  1884.     pDrvCtrl->idr.ac_if.if_flags &= ~(IFF_UP | IFF_RUNNING );
  1885.     logMsg ("dc%d -- Restartedn", unit,0,0,0,0,0);
  1886.     status = DC_CSR_READ (pDrvCtrl->devAdrs, CSR6);
  1887.     DC_CSR_WRITE (pDrvCtrl->devAdrs, CSR6, 0); /* reset mode register */
  1888.     for (ix = 0; ix < pDrvCtrl->dcNumRds; ix++, rmd++)
  1889.         {
  1890. /* buffer size */
  1891. rmd->rDesc1 = PCISWAP(RDESC1_RBS1_VAL(DC_BUFSIZ) | 
  1892.       RDESC1_RBS2_VAL(0));
  1893. if (ix == (pDrvCtrl->dcNumRds - 1)) /* if its is last one */
  1894. rmd->rDesc1 |= PCISWAP(RDESC1_RER); /* end of receive ring */
  1895. rmd->rDesc0 = PCISWAP(RDESC0_OWN); /* give ownership to lance */
  1896.         }
  1897.     for (ix = 0; ix < pDrvCtrl->dcNumTds; ix++, tmd++)
  1898.         {
  1899. tmd->tDesc1 = PCISWAP((TDESC1_TBS1_PUT(0) |
  1900.        TDESC1_TBS2_PUT(0) |
  1901.        TDESC1_IC   |  /* intrpt on xmit */
  1902.        TDESC1_LS          | /* last segment */
  1903.        TDESC1_FS)); /* first segment */
  1904. if (ix == (pDrvCtrl->dcNumTds - 1)) /* if its is last one */
  1905.     tmd->tDesc1 |= PCISWAP(TDESC1_TER); /* end of Xmit ring */
  1906. tmd->tDesc0 = 0 ; /* clear status */
  1907.         }
  1908.     /* clear the status register */
  1909.     DC_CSR_WRITE (pDrvCtrl->devAdrs, CSR5, 0xffffffff);
  1910.     DC_CSR_WRITE (pDrvCtrl->devAdrs, CSR6, status); /* restore mode */
  1911.     pDrvCtrl->idr.ac_if.if_flags |= (IFF_UP | IFF_RUNNING | IFF_NOTRAILERS);
  1912.     }
  1913. /*******************************************************************************
  1914. *
  1915. * dcLoanFree - return the given buffer to loaner pool
  1916. *
  1917. * This routine returns <pRxBuf> to the pool of available loaner buffers.
  1918. * It also returns <pRef> to the pool of available loaner reference counters,
  1919. * then zeroes the reference count.
  1920. *
  1921. * RETURNS: N/A
  1922. */
  1923.  
  1924. LOCAL void dcLoanFree
  1925.     (
  1926.     DRV_CTRL * pDrvCtrl, /* pointer to device control structure */
  1927.     char * pRxBuf, /* pointer to receive buffer to free */
  1928.     UINT8 * pRef /* pointer to reference count */
  1929.     )
  1930.     {
  1931.     /* return loaned buffer to pool */
  1932.  
  1933.     pDrvCtrl->lPool[pDrvCtrl->nLoanRx] = pRxBuf;
  1934.  
  1935.     /* return loaned reference count to pool */
  1936.  
  1937.     pDrvCtrl->pRefCnt[pDrvCtrl->nLoanRx++] = pRef;
  1938.     /* reset reference count - should have been done from above, but... */
  1939.  
  1940.     *pRef = 0;
  1941.     }
  1942. /*******************************************************************************
  1943. *
  1944. * dcEnetAddrGet - gets the ethernet address from the ROM register.
  1945. *
  1946. * This routine gets the ethernet address from the ROM register.
  1947. * This routine returns the ethernet address into the pointer supplied to it.
  1948. * RETURNS: OK/ERROR
  1949. */
  1950. LOCAL STATUS dcEnetAddrGet
  1951.     (
  1952.     ULONG devAdrs, /* device base I/O address */
  1953.     char *  enetAdrs, /* pointer to the ethernet address */ 
  1954.     int len /* number of bytes to read */
  1955.     )
  1956.     {
  1957.     FAST ULONG csr9Value; /* register to hold CSR9 */
  1958.     int ix; /* index register */
  1959.     BOOL eRomReady = FALSE; /* ethernet ROM register state */
  1960.     DC_CSR_WRITE (devAdrs, CSR9, 0); /* reset rom pointer */
  1961.     while (len > 0)
  1962. {
  1963. for (ix = 0; ix < 10; ix++) /* try at least 10 times */
  1964.     {
  1965.     if ((csr9Value = DC_CSR_READ (devAdrs, CSR9)) & CSR9_040_DNVAL)
  1966. {
  1967. eRomReady = FALSE;
  1968.      DELAY(500);
  1969. }
  1970.     else
  1971. {
  1972. *enetAdrs++ = (UCHAR) csr9Value;
  1973. len--;
  1974. eRomReady = TRUE;
  1975. break;
  1976. }
  1977.        }
  1978.         
  1979.         if (!eRomReady)
  1980.             break;
  1981. }
  1982.     if (!eRomReady)
  1983.      return (ERROR);
  1984.     else
  1985. return (OK);
  1986.     }
  1987. /*******************************************************************************
  1988. *
  1989. * dc21140EnetAddrGet - gets the ethernet address from the ROM register 
  1990. *
  1991. * This routine gets the last two bytes of the ethernet address from the ROM
  1992. * register and concantenates this value to the predefined values for DEC PMCs..
  1993. * This routine returns the ethernet address into the pointer supplied to it.
  1994. *
  1995. * The procedure could be expanded in the future to allow for modification of
  1996. * Ethernet addresses in the serial ROM.  It will have to be modified to
  1997. * accomodate the differences in the onboard 100Mb/s ethernet on future 
  1998. * Motorola products.
  1999. * RETURNS: OK/ERROR
  2000. */
  2001. LOCAL STATUS dc21140EnetAddrGet
  2002.     (
  2003.     ULONG devAdrs, /* device base I/O address */
  2004.     char *  enetAdrs, /* pointer to the ethernet address */ 
  2005.     int len /* number of bytes to read */
  2006.     )
  2007.     {
  2008.     int i; /* index register */
  2009.     int ix; /* index register */
  2010.     int tmpInt; /* temporary int */
  2011.     union SROMData
  2012. {
  2013. char Char[6]; /* temporary 6 x Char */
  2014. USHORT Short[2]; /* temporary USHORT */
  2015. ULONG   Long; /* temporay ULONG */
  2016. } SROMData;
  2017.     /* Check if SROM is programmed. */
  2018.     SROMData.Short[0] = dcReadRom (devAdrs, 0);
  2019.     if (SROMData.Short[0] == 0xFFFF) 
  2020. {
  2021. /* SROM is unprogrammed, get MAC address from NVRAM. */
  2022. sysNvRamGet ((char *)enetAdrs, 6, ((int) ((char *)(0x1f2c)) - 256));
  2023. return (OK);
  2024. }
  2025.     else 
  2026. {
  2027. /* Look for Legacy Format in ROM. */
  2028. SROMData.Short[0] = dcReadRom (devAdrs, 13);
  2029. if (SROMData.Short[0] == 0xAA55) 
  2030.     {
  2031.     /*
  2032.      * Read from location 0 in ROM.  MAC address appears at
  2033.      * location 0 in Legacy SROM formats.
  2034.      */
  2035.     tmpInt = 0;
  2036.     }
  2037. else 
  2038.     {
  2039.     /*
  2040.      * Read from location 20 in ROM.  MAC address appears at
  2041.      * location 20 (10 byte pairs) in both Version 1/A and 3.0 
  2042.      * SROM formats.
  2043.      */
  2044.     tmpInt = DEC_PMC_POS;
  2045.     }
  2046. for (i = tmpInt, ix = 0; i<(3+tmpInt); i++, ix++) 
  2047.     {
  2048.     if ((UINT)(SROMData.Short[0] = dcReadRom (devAdrs, i)) == ERROR) 
  2049. {
  2050. return (ERROR);
  2051. }
  2052.     enetAdrs[ix++] = SROMData.Char[1];
  2053.     enetAdrs[ix] = SROMData.Char[0];
  2054.     }
  2055. }
  2056.     tmpInt = -1;
  2057.     return (OK);
  2058.     }
  2059. /*******************************************************************************
  2060. *
  2061. * dcFltrFrmXmit - Transmit the setup filter frame.
  2062. *
  2063. * This routine transmits the setup filter frame.
  2064. * The setup frame is not transmitted actually over the wire. The setup frame
  2065. * which is transmitted is 192 bytes. The tranmitter should be in an on state
  2066. * before this function is called. This call has been coded so that the 
  2067. * setup frame can be transmitted after the chip is done with the 
  2068. * intialization taking into consideration for adding multicast support.
  2069. * RETURNS: OK/ERROR
  2070. */
  2071. LOCAL int dcFltrFrmXmit
  2072.     (
  2073.     DRV_CTRL * pDrvCtrl,  /* pointer to device control structure */
  2074.     char *  pPhysAdrsTbl,  /* pointer to physical address table */ 
  2075.     int  tblLen /* size of the physical address table */
  2076.     )
  2077.     {
  2078.     DC_TDE * tmd; /* pointer to Tx ring descriptor */
  2079.     ULONG *  pBuff; /* pointer to the Xmit buffer */
  2080.     int status = OK; /* intialize status as OK */
  2081.     ULONG csr7Val; /* value in CSR7 */
  2082.     semTake (pDrvCtrl->TxSem, WAIT_FOREVER);
  2083.     if (dcFltrFrmSetup (pDrvCtrl, pPhysAdrsTbl, tblLen) != OK)
  2084. {
  2085. status = ERROR; /* not able to set up filter frame */
  2086. goto setupDone; /* set up done */
  2087. }
  2088.     /* See if next TXD is available */
  2089.     tmd = pDrvCtrl->txRing + pDrvCtrl->txIndex;
  2090.     DC_CACHE_INVALIDATE (tmd, TMD_SIZ);
  2091.     if  (
  2092.         ((tmd->tDesc0 & PCISWAP(TDESC0_OWN)) != 0) ||
  2093.         (
  2094.         ((pDrvCtrl->txIndex + 1) % pDrvCtrl->dcNumTds) == pDrvCtrl->txDiIndex
  2095. )
  2096.         )
  2097. {
  2098. status = ERROR; /* not able to set up filter frame */
  2099. goto setupDone; /* set up done */
  2100. }
  2101.     /* Get pointer to transmit buffer */
  2102.     pBuff = DC_CACHE_PHYS_TO_VIRT(PCI_TO_MEM_PHYS(PCISWAP(tmd->tDesc2)));
  2103.     /* copy into Xmit buffer */
  2104.     bcopyLongs ((char *)pDrvCtrl->pFltrFrm, (char *)pBuff, 
  2105. FLTR_FRM_SIZE_ULONGS);
  2106.     tmd->tDesc0 = 0; /* clear buffer error status */
  2107.     tmd->tDesc1 |= PCISWAP(TDESC1_SET); /* frame type as set up */
  2108.     tmd->tDesc1 &= PCISWAP(~TDESC1_TBS1_MSK);
  2109.     tmd->tDesc1 |= PCISWAP(TDESC1_TBS1_PUT(FLTR_FRM_SIZE));
  2110.     tmd->tDesc0 = PCISWAP(TDESC0_OWN);  /* give ownership to device */
  2111.     CACHE_PIPE_FLUSH (); /* Flush the write pipe */
  2112.     /* Advance our management index */
  2113.     pDrvCtrl->txIndex = (pDrvCtrl->txIndex + 1) % pDrvCtrl->dcNumTds;
  2114.     pDrvCtrl->txDiIndex = (pDrvCtrl->txDiIndex + 1) % pDrvCtrl->dcNumTds;
  2115.     csr7Val = DC_CSR_READ (pDrvCtrl->devAdrs, CSR7);
  2116.     DC_CSR_WRITE (pDrvCtrl->devAdrs, CSR7, 0); /* mask interrupts */
  2117.     
  2118.     if (dcKickStartTx)
  2119.      DC_CSR_WRITE (pDrvCtrl->devAdrs, CSR1, CSR1_TPD);   /* xmit poll demand */
  2120.     /* wait for the own bit to change */
  2121.     while (tmd->tDesc0 & PCISWAP (TDESC0_OWN))
  2122. /* do nothing */ ;
  2123.     tmd->tDesc0 = 0; /* clear status bits */
  2124.     tmd->tDesc1 &= PCISWAP(~TDESC1_SET);
  2125.     DC_CSR_WRITE (pDrvCtrl->devAdrs, CSR7, csr7Val); /* restore value */
  2126. setupDone:
  2127.     /* Release exclusive access. */
  2128.     semGive (pDrvCtrl->TxSem);
  2129.     return (status);
  2130.     }
  2131. /*******************************************************************************
  2132. *
  2133. * dcFltrFrmSetup - set up the filter frame.
  2134. *
  2135. * This routine sets up the filter frame to filter the physical addresses
  2136. * on the incoming frames. The setup filter frame buffer is 192 bytes. This
  2137. * setup frame needs to be transmitted before transmitting and receiving 
  2138. * any frames. 
  2139. * RETURNS: OK/ERROR
  2140. */
  2141. LOCAL int dcFltrFrmSetup
  2142.     (
  2143.     DRV_CTRL * pDrvCtrl,  /* pointer to device control structure */
  2144.     char *  pPhysAdrsTbl,  /* pointer to physical address table */ 
  2145.     int  tblLen /* size of the physical address table */
  2146.     )
  2147.     {
  2148.     int ix; /* index variable */
  2149.     int jx;  /* inner index variable */
  2150.     ULONG * pFltrFrm; /* pointer to the filter frame */
  2151.     USHORT * pPhysAddrs; /* pointer to the physical addresses */
  2152.     if (tblLen > FLTR_FRM_ADRS_NUM)
  2153. return (ERROR);
  2154.     pFltrFrm = pDrvCtrl->pFltrFrm;
  2155.     for (ix = 0; ix < FLTR_FRM_SIZE_ULONGS; ix++)
  2156. *pFltrFrm++ = FLTR_FRM_DEF_ADRS;
  2157.     pFltrFrm = pDrvCtrl->pFltrFrm;
  2158.     pPhysAddrs = (USHORT *) (pPhysAdrsTbl);
  2159.     for (ix = 0; ix < tblLen; ix++)
  2160. {
  2161. for (jx = 0; jx < (FLTR_FRM_ADRS_SIZE/sizeof (USHORT)); jx++)
  2162.     {
  2163. #if (_BYTE_ORDER == _BIG_ENDIAN)
  2164.     *pFltrFrm =  (*pPhysAddrs << 16);
  2165. #else
  2166.     *pFltrFrm = ((LSB(*pPhysAddrs) << 8) | MSB(*pPhysAddrs));
  2167. #endif
  2168.     pPhysAddrs++;
  2169.     pFltrFrm++;
  2170.     }
  2171. }
  2172.     return (OK);
  2173.     }
  2174. /*******************************************************************************
  2175. *
  2176. * dcReadRom - reads an specified entry in the Serial ROM 
  2177. *
  2178. * This routine uses the line number passed to the function and returns
  2179. * the two bytes of information that is associated with it.  This will later
  2180. * be used by the dc21140GetEthernetAdr function.  It can also be used to 
  2181. * review the ROM contents itself.
  2182. *
  2183. * The function must first send some initial bit paterns to the CSR9 which 
  2184. * contains the Serial ROM Control bits.  Then the line index into the ROM
  2185. * will be evaluated bit by bit to program the ROM.  The 2 bytes of data
  2186. * will be extracted and processed into a normal pair of bytes. 
  2187. * RETURNS: Short Value in ROM/ERROR
  2188. */
  2189. LOCAL USHORT dcReadRom
  2190.     (
  2191.     ULONG devAdrs, /* device base I/O address */
  2192.     UCHAR lineCnt  /* Serial ROM line Number */ 
  2193.     )
  2194.     {
  2195.     int ix; /* index register */
  2196.     int intCnt; /* address loop count */
  2197.     USHORT tmpShort;
  2198.     ULONG tmpLong; 
  2199.     /* Is the line offset valid, and if so, how large is it */
  2200.     if (lineCnt > SROM_SIZE)
  2201.      {
  2202. logMsg ("dcReadRom FAILED, bad lineCntn",0,0,0,0,0,0);
  2203.      return (ERROR);
  2204.      }
  2205.     if (lineCnt < 64)
  2206.      {
  2207. intCnt = 6;
  2208. lineCnt = lineCnt << 2;  /* Prepare lineCnt for processing */
  2209.      }
  2210.     else
  2211. intCnt = 8;
  2212.     /* Command the Serial ROM to the correct Line */
  2213.     /* Preamble of Command */
  2214.     DC_SROM_WRITE (devAdrs, 0x00000000, 30); /* Command 1 */
  2215.     DC_SROM_WRITE (devAdrs, 0x00000001, 50); /* Command 2 */
  2216.     DC_SROM_WRITE (devAdrs, 0x00000003, 250); /* Command 3 */
  2217.     DC_SROM_WRITE (devAdrs, 0x00000001, 100); /* Command 4 */
  2218.     /* Command Phase */
  2219.     DC_SROM_WRITE (devAdrs, 0x00000005, 150); /* Command 5 */
  2220.     DC_SROM_WRITE (devAdrs, 0x00000007, 250); /* Command 6 */
  2221.     DC_SROM_WRITE (devAdrs, 0x00000005, 250); /* Command 7 */
  2222.     DC_SROM_WRITE (devAdrs, 0x00000007, 250); /* Command 8 */
  2223.     DC_SROM_WRITE (devAdrs, 0x00000005, 100); /* Command 9 */
  2224.     DC_SROM_WRITE (devAdrs, 0x00000001, 150); /* Command 10 */
  2225.     DC_SROM_WRITE (devAdrs, 0x00000003, 250); /* Command 11 */
  2226.     DC_SROM_WRITE (devAdrs, 0x00000001, 100); /* Command 12 */
  2227.     
  2228.     /* Address Phase */
  2229.     for (ix = 0; ix < intCnt; ix++)
  2230.      {
  2231. tmpLong = (lineCnt & 0x80) >> 5; /* Extract and move bit to bit 3) */
  2232. /* Write the command */
  2233.      DC_SROM_WRITE (devAdrs, tmpLong | 0x00000001, 150);  /* Command 13 */
  2234.      DC_SROM_WRITE (devAdrs, tmpLong | 0x00000003, 250);  /* Command 14 */
  2235.      DC_SROM_WRITE (devAdrs, tmpLong | 0x00000001, 100);  /* Command 15 */
  2236. lineCnt <<= 1;  /* Adjust significant address bit */
  2237.      }
  2238.     NSDELAY (150);
  2239.     /* Data Phase */
  2240.     tmpShort =0;
  2241.     for (ix = 15; ix >= 0; ix--)
  2242.      {
  2243. /* Write the command */
  2244.      DC_SROM_WRITE (devAdrs, 0x00000003, 100); /* Command 16 */
  2245. /* Extract the data */
  2246.      tmpShort |= DC_SROM_READ (devAdrs) << ix;  /* Command 17 */
  2247.      NSDELAY (150);
  2248.         
  2249.      DC_SROM_WRITE (devAdrs, 0x00000001, 250); /* Command 18 */
  2250.      }
  2251.     /* Finish up command */
  2252.     DC_SROM_WRITE (devAdrs, 0x00000000, 100); /* Command 19 */
  2253.     return (tmpShort);
  2254.     }
  2255. /*******************************************************************************
  2256. * dcReadAllRom - read entire serial rom
  2257. *
  2258. * Function to read all of serial rom and store the data in the
  2259. * data structure passed to the function.  The count value will
  2260. * indicate how much of the serial rom to read.  The routine with also
  2261. * swap the the bytes as the come in. 
  2262. *
  2263. * RETURNS: N/A.
  2264. */
  2265. void dcReadAllRom
  2266.     (
  2267.     ULONG devAdrs, /* device base I/O address */
  2268.     UCHAR *buffer, /* destination bufferr */ 
  2269.     int cnt             /* Amount to extract in bytes */
  2270.     )
  2271.     {
  2272.     USHORT total, index;
  2273.     union tmp_type {
  2274.         USHORT Short;
  2275.      char   Byte [2]; /* temporary 2 by char */
  2276.     } tmp;
  2277.     total = 0;
  2278.     for (index = 0, total = 0; total < cnt / 2; index += 2, total++)
  2279.      {
  2280. tmp.Short = dcReadRom (devAdrs, total);
  2281. buffer[index] = tmp.Byte[1];
  2282. buffer[index+1] = tmp.Byte[0];
  2283.      }
  2284.     }
  2285. #ifdef DC_DEBUG
  2286. /*******************************************************************************
  2287. *
  2288. * dcViewRom - display lines of serial ROM for dec21140
  2289. *
  2290. * RETURNS: Number of bytes displayed.
  2291. */
  2292. int dcViewRom
  2293.     (
  2294.     ULONG devAdrs, /* device base I/O address */
  2295.     UCHAR lineCnt, /* Serial ROM line Number */ 
  2296.     int cnt             /* Amount to display */
  2297.     )
  2298.     {
  2299.     USHORT total;
  2300.     union tmp_type 
  2301.      {
  2302.         USHORT Short;
  2303.      char   Byte [2]; /* temporary 2 by char */
  2304.      } tmp;
  2305.     if (((lineCnt / 2) < 0) || ((lineCnt / 2) > (UCHAR) SROM_SIZE))
  2306. return (ERROR);
  2307.     total = 0;
  2308.     while (((lineCnt / 2) < SROM_SIZE) && (cnt > 0))
  2309.      {
  2310. if (!(total % 16))
  2311.     printf ("nValues for line %2d =>0x  ", total);
  2312. tmp.Short = dcReadRom (devAdrs, lineCnt);
  2313. printf ("%4x ",tmp.Short);
  2314. lineCnt++ ;
  2315. total += 2;
  2316. cnt -= 2;
  2317. }
  2318.     printf ("n");
  2319.     return (total);
  2320.     }
  2321. /*******************************************************************************
  2322. *
  2323. * dcCsrShow - display dec 21040/21140 status registers 0 thru 15
  2324. *
  2325. * Display the 16 registers of the DEC 21140 device on the console.
  2326. * Each register is printed in hexadecimal format.
  2327. *
  2328. * RETURNS: N/A.
  2329. */
  2330. int dcCsrShow
  2331.     (
  2332.     int unit
  2333.     )
  2334.     {
  2335.     DRV_CTRL *pDrvCtrl;
  2336.     int devAdrs;
  2337.     if (unit > MAX_UNITS)
  2338.         return -1;
  2339.     pDrvCtrl = &drvCtrl[unit];
  2340.     if (!pDrvCtrl->attached)
  2341.         return -2;
  2342.     devAdrs=pDrvCtrl->devAdrs;
  2343.     
  2344.     printf ("dc%d Configuration Registers: n", unit);
  2345.     printf (" 0=0x%x, 1=0x%x, 2=0x%x, 3=0x%xn",
  2346.             (int) DC_CSR_READ (devAdrs, CSR0),
  2347.             (int) DC_CSR_READ (devAdrs, CSR1),
  2348.             (int) DC_CSR_READ (devAdrs, CSR2),
  2349.             (int) DC_CSR_READ (devAdrs, CSR3));
  2350.     printf (" 4=0x%x, 5=0x%x, 6=0x%x, 7=0x%xn",
  2351.             (int) DC_CSR_READ (devAdrs, CSR4),
  2352.             (int) DC_CSR_READ (devAdrs, CSR5),
  2353.             (int) DC_CSR_READ (devAdrs, CSR6),
  2354.             (int) DC_CSR_READ (devAdrs, CSR7));
  2355.     printf (" 8=0x%x, 9=0x%x, 10=0x%x, 11=0x%xn",
  2356.             (int) DC_CSR_READ (devAdrs, CSR8),
  2357.             (int) DC_CSR_READ (devAdrs, CSR9),
  2358.             (int) DC_CSR_READ (devAdrs, CSR10),
  2359.             (int) DC_CSR_READ (devAdrs, CSR11));
  2360.     printf (" 12=0x%x, 13=0x%x, 14=0x%x, 15=0x%xn",
  2361.             (int) DC_CSR_READ (devAdrs, CSR12),
  2362.             (int) DC_CSR_READ (devAdrs, CSR13),
  2363.             (int) DC_CSR_READ (devAdrs, CSR14),
  2364.             (int) DC_CSR_READ (devAdrs, CSR15));
  2365.     return 0;
  2366.     }
  2367. int dcShow
  2368.     (
  2369.     UINT unit
  2370.     )
  2371.     {
  2372.     DRV_CTRL *pDrvCtrl;
  2373.     DC_STATS *pErrStats;
  2374.     if (unit > MAX_UNITS)
  2375.         return -1;
  2376.     pDrvCtrl = &drvCtrl[unit];
  2377.     if (!pDrvCtrl->attached)
  2378.         return -2;
  2379.     pErrStats=&pDrvCtrl->errStats;
  2380.     printf ("dc%d: pDrvCtrl=0x%xn", unit, (int)pDrvCtrl);
  2381.     printf (" ivec=%d ilevel=%d devAdrs=0x%x pciMemBase=0x%x memWidth=%dn",
  2382.             (int) pDrvCtrl->ivec,
  2383.             (int) pDrvCtrl->ilevel,
  2384.             (int) pDrvCtrl->devAdrs,
  2385.             (int) pDrvCtrl->pciMemBase,
  2386.             (int) pDrvCtrl->memWidth);
  2387.     printf (" nTDs=%d nRDs=%d rxIndex=%d txIndex=%d nLoanRx=%dn",
  2388.             (int) pDrvCtrl->dcNumTds,
  2389.             (int) pDrvCtrl->dcNumRds,
  2390.             (int) pDrvCtrl->rxIndex,
  2391.             (int) pDrvCtrl->txIndex,
  2392.             (int) pDrvCtrl->nLoanRx);
  2393.     printf (" ipackets=%d, opackets=%d ierrors=%d oerrors=%d collisions=%dn",
  2394.             (int) pDrvCtrl->idr.ac_if.if_ipackets,
  2395.             (int) pDrvCtrl->idr.ac_if.if_opackets,
  2396.             (int) pDrvCtrl->idr.ac_if.if_ierrors,
  2397.             (int) pDrvCtrl->idr.ac_if.if_oerrors,
  2398.             (int) pDrvCtrl->idr.ac_if.if_collisions);
  2399.     printf (" len=%d maxQlen=%d drops=%d txIndex=%d txDiIndex=%dn",
  2400.             pDrvCtrl->idr.ac_if.if_snd.ifq_len,
  2401.             pDrvCtrl->idr.ac_if.if_snd.ifq_maxlen,
  2402.             pDrvCtrl->idr.ac_if.if_snd.ifq_drops,
  2403.             pDrvCtrl->txIndex,
  2404.             pDrvCtrl->txDiIndex);
  2405.     printf (" txstats: jbr=%d lostCarr=%d noCarr=%d lateColl=%d XsColl=%dn",
  2406.             pErrStats->txJbrTmo,
  2407.             pErrStats->txLostCarrier,
  2408.             pErrStats->txNoCarrier,
  2409.             pErrStats->txLateCollision,
  2410.             pErrStats->txExsCollision);
  2411.     
  2412.     printf ("          hbFail=%d lnkF=%d uflo=%d defr=%d retries=%dn",
  2413.             pErrStats->txHeartBeatFail,
  2414.             pErrStats->txLinkFail,
  2415.             pErrStats->txUnderflow,
  2416.             pErrStats->txDeferred,
  2417.             pErrStats->txRetries);
  2418.     printf ("          drops=%d fl=%d fl_need=%d fl_done=%d QMax=%d QCur=%dn",
  2419.             pErrStats->txDropped,     
  2420.             pErrStats->txFlushCalled,
  2421.             pErrStats->txFlushNeeded,
  2422.             pErrStats->txFlushDone, 
  2423.             pErrStats->txQsizeMax,   
  2424.             pErrStats->txQsizeCur);    
  2425.     
  2426.     printf (" rxstats: fltErr=%d DescErr=%d Runt=%d tooLng=%d Coll=%dn",
  2427.             pErrStats->rxFiltrErr, 
  2428.             pErrStats->rxDescErr,  
  2429.             pErrStats->rxRuntFrm,   
  2430.             pErrStats->rxTooLong,   
  2431.             pErrStats->rxCollision);
  2432.     printf ("          dribl=%d crc=%d ovflo=%d miiErr=%d miss=%d rxlatn=%dn",
  2433.             pErrStats->rxDribbleBit,
  2434.             pErrStats->rxCrcErr,
  2435.             pErrStats->rxOverflow,
  2436.             pErrStats->rxMiiErr,
  2437.             pErrStats->rxMissed,
  2438.             pErrStats->rxLatency);    
  2439.             
  2440.     return 0;
  2441.     }
  2442. void phyProbe
  2443.     (
  2444.     DRV_CTRL *pDrvCtrl
  2445.     )
  2446.     {
  2447.     int phyAdrs;
  2448.     for (phyAdrs=0; phyAdrs < DC_MAX_PHY; phyAdrs++)
  2449.         {
  2450.         printf ("%d = 0x%x ", phyAdrs,
  2451.                 dcMiiPhyRead (pDrvCtrl, phyAdrs, MII_PHY_ID0));
  2452.         }
  2453.     }
  2454. void phyShow
  2455.     (
  2456.     DRV_CTRL *pDrvCtrl,
  2457.     int phyNum
  2458.     )
  2459.     {
  2460.     int reg;
  2461.     printf ("CR=0x%x SR=0x%x IDO=0x%x ID1=0x%xn",
  2462.             dcMiiPhyRead (pDrvCtrl, phyNum, MII_PHY_CR),
  2463.             dcMiiPhyRead (pDrvCtrl, phyNum, MII_PHY_SR),
  2464.             dcMiiPhyRead (pDrvCtrl, phyNum, MII_PHY_ID0),
  2465.             dcMiiPhyRead (pDrvCtrl, phyNum, MII_PHY_ID1));
  2466.     printf ("ANA=0x%x ANLPA=0x%x ANE=0x%x ANP=0x%xn",
  2467.             dcMiiPhyRead (pDrvCtrl, phyNum, MII_PHY_ANA),
  2468.             dcMiiPhyRead (pDrvCtrl, phyNum, MII_PHY_ANLPA),
  2469.             dcMiiPhyRead (pDrvCtrl, phyNum, MII_PHY_ANE),
  2470.             dcMiiPhyRead (pDrvCtrl, phyNum, MII_PHY_ANP));
  2471.     }
  2472. #endif /* DC_DEBUG */