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

VxWorks

开发平台:

C/C++

  1. /* sh7615End.c - sh7615End END  network interface driver */
  2. /* Copyright 1984-2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01l,28mar02,h_k  added muxError() at failing of netClusterGet() and
  8.                  netClBlkGet(). moved E-DMAC Receive Request enable to
  9.                  sh7615EndRcvIntHandle() from sh7615EndInt(). added setting
  10.                  depth of FIFO. changed clNum and mBlkNum. (SPR #74021)
  11. 01k,02nov01,zl   corrected NULL usage.
  12. 01j,19oct01,zl   documentation fixes. Removed sh7615EndIASetup().
  13. 01i,09may01,zl   detect link status change, add restart routine.
  14. 01h,05may01,zl   made interrupt handling more efficient and robust.
  15. 01g,30apr01,zl   detect and set full duplex mode.
  16. 01f,09nov00,rsh  missing #ifdef
  17. 01e,02nov00,frf  Read and Write functions to a PHY registers:
  18.                        dp83843RegRead, dp83843RegWrite, dp83843RegPrint.
  19. 01d,10oct00,zl   got polled mode working. Code Cleanup.
  20. 01c,27sep00,rsh  add cache support.
  21. 01b,26sep00,rsh  remove bsp option to provide shared memory since this chip.
  22.                  doesn't provide special memory.
  23. 01a,16aug00,rsh  written based on dec21x40End.c
  24. */
  25. /*
  26. DESCRIPTION
  27. This module implements an network interface driver for the Hitachi SH7615
  28. on-chip Ethernet controller (EtherC) and EtherNet COntroller Direct Memory 
  29. Access Controller (E-DMAC). The EtherC is fully compliant with the IEEE 802.3
  30. 10Base-T and 100Base-T specifications. Hardware support of the Media 
  31. Independent Interface (MII) is off-chip.
  32. The Ethernet controller is connected to dedicated transmit and receive 
  33. Ethernet DMACs (E-DMACs) in the SH7615, and carries out high-speed data
  34. transfer to and from memory. The operation of the E-DMAC is controlled with
  35. the transmit and receive descriptor rings. The start address of the
  36. descriptors is set in the RDLAR and TDLAR registers, so they can reside
  37. anywhwere. The descriptors must reside on boundaries that are multiple
  38. of their size (16, 32, or 64 bytes).
  39. EXTERNAL INTERFACE
  40.  
  41. The driver provides the standard external interface, sh7615EndLoad(), which
  42. takes a string of colon-separated parameters. The parameters should be 
  43. specified in hexadecimal, optionally preceeded by "0x" or a minus sign "-".
  44. The parameter string is parsed using strtok_r() and each parameter is
  45. converted from a string representation to binary by a call to
  46. strtoul(parameter, NULL, 16).
  47. The format of the parameter string is:
  48. "<ivec>:<ilevel>:<numRds>:<numTds>:<phyDefMode>:<userFlags>"
  49. TARGET-SPECIFIC PARAMETERS
  50. .IP <ivec>
  51. This is the interrupt vector number of the hardware interrupt generated by
  52. this Ethernet device.  The driver uses intConnect() to attach an interrupt
  53. handler for this interrupt.
  54. .IP <ilevel>
  55. This parameter defines the level of the hardware interrupt.
  56. .IP <numRds>
  57. The number of receive descriptors to use.  This controls how much data
  58. the device can absorb under load.  If this is specified as NONE (-1), 
  59. the default of 32 is used.
  60. .IP <numTds>
  61. The number of transmit descriptors to use.  This controls how much data
  62. the device can absorb under load.  If this is specified as NONE (-1) then
  63. the default of 64 is used.
  64. .IP <phyDefMode>
  65. This parameter specifies the operating mode that will be set up
  66. by the default physical layer initialization routine in case all
  67. the attempts made to establish a valid link failed. If that happens,
  68. the first PHY that matches the specified abilities will be chosen to
  69. work in that mode, and the physical link will not be tested.
  70. .IP <userFlags>
  71. This field enables the user to give some degree of customization to the
  72. driver.
  73. Bit [0-3] reserved for receive FIFO depth and bit [4-7] reserved for transmit
  74. FIFO depth. The actual FIFO size is 256 times + 256 the set value for each
  75. FIFO. The max FIFO depth is 512 bytes for SH7615 (i.e. 0x1 for receive FIFO,
  76. 0x10 for transmit FIFO) and 2048 bytes for SH7616 (i.e. 0x7 for receive FIFO,
  77. 0x70 for transmit FIFO).
  78. The macros SYS_INT_CONNECT, SYS_INT_DISCONNECT, and SYS_INT_ENABLE allow
  79. the driver to be customized for BSPs that use special versions of these
  80. routines.
  81. The macro SYS_INT_CONNECT is used to connect the interrupt handler to
  82. the appropriate vector.  By default it is the routine intConnect().
  83. The macro SYS_INT_DISCONNECT is used to disconnect the interrupt handler prior
  84. to unloading the module.  By default this is a dummy routine that
  85. returns OK.
  86. The macro SYS_INT_ENABLE is used to enable the interrupt level for the
  87. end device.  It is called once during initialization.  By default this is
  88. the routine sysLanIntEnable(), defined in the module sysLib.o.
  89. The macro SYS_ENET_ADDR_GET is used to get the ethernet address (MAC)
  90. for the device.  The single argument to this routine is the SH7615END_DRV_CTRL
  91. pointer.  By default this routine copies the ethernet address stored in
  92. the global variable sysTemplateEnetAddr into the SH7615END_DRV_CTRL structure.
  93. SEE ALSO: muxLib, endLib
  94. .I "Writing and Enhanced Network Driver"
  95. .I "SH7615 Hardware Manual"
  96. */
  97. /* includes */
  98. #include "vxWorks.h"
  99. #include "stdlib.h"
  100. #include "cacheLib.h"
  101. #include "intLib.h"
  102. #include "end.h" /* Common END structures. */
  103. #include "endLib.h"
  104. #include "lstLib.h" /* Needed to maintain protocol list. */
  105. #include "wdLib.h"
  106. #include "iv.h"
  107. #include "semLib.h"
  108. #include "etherLib.h"
  109. #include "logLib.h"
  110. #include "netLib.h"
  111. #include "stdio.h"
  112. #include "sysLib.h"
  113. #include "errno.h"
  114. #include "errnoLib.h"
  115. #include "memLib.h"
  116. #include "iosLib.h"
  117. #undef ETHER_MAP_IP_MULTICAST
  118. #include "etherMultiLib.h" /* multicast stuff. */
  119. #include "net/mbuf.h"
  120. #include "net/unixLib.h"
  121. #include "net/protosw.h"
  122. #include "net/systm.h"
  123. #include "net/if_subr.h"
  124. #include "net/route.h"
  125. #include "sys/socket.h"
  126. #include "sys/ioctl.h"
  127. #include "sys/times.h"
  128. #include "drv/end/sh7615End.h"
  129. /* defines */
  130. #define INCLUDE_PHY
  131. #define DRV_CTRL SH7615END_DRV_CTRL
  132. #define SH7615END_DEV_NAME "shend"
  133. #define SH7615END_DEV_NAME_LEN 6
  134. #define SH7615END_BUFSIZ (ETHERMTU + ENET_HDR_REAL_SIZ + 6 +     
  135.     SH7615END_BD_ALIGN)
  136. #define SH7615END_SPEED 10000000 /* 10Mbs */
  137.     
  138. /* DRV_CTRL flags */
  139. #define SH7615END_INV_TBD_NUM   0x02  /* invalid numTds provided */
  140. #define SH7615END_INV_RBD_NUM   0x04  /* invalid numRds provided */
  141. #define SH7615END_POLLING       0x08  /* Poll mode, io mode */
  142. #define SH7615END_PROMISC       0x20  /* Promiscuous, rx mode */
  143. #define SH7615END_MCAST         0x40  /* Multicast, rx mode */
  144. #define SH7615END_FD            0x80  /* full duplex mode */
  145. /*
  146.  * Default macro definitions for BSP interface.
  147.  * These macros can be redefined in a wrapper file, to generate
  148.  * a new module with an optimized interface.
  149.  */
  150. #ifndef SYS_INT_CONNECT
  151. #define SYS_INT_CONNECT(pDrvCtrl,rtn,arg,pResult)                       
  152.     {                                                                   
  153.     *pResult = intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (pDrvCtrl->ivec),
  154.                              rtn, (int)arg);                            
  155.     }
  156. #endif /* SYS_INT_CONNECT */
  157.  
  158. #ifndef SYS_INT_DISCONNECT
  159. #define SYS_INT_DISCONNECT(pDrvCtrl,rtn,arg,pResult)                    
  160.     {                                                                   
  161.     *pResult = OK;                                                      
  162.     }
  163. #endif /* SYS_INT_DISCONNECT */
  164. #ifndef SYS_INT_ENABLE
  165. #define SYS_INT_ENABLE(pDrvCtrl)                                        
  166.     {                                                                   
  167.     IMPORT void sysLanIntEnable();                                      
  168.     sysLanIntEnable (pDrvCtrl->ilevel);                                 
  169.     }
  170. #endif /* SYS_INT_ENABLE */
  171.  
  172. #ifndef SYS_INT_DISABLE
  173. #define SYS_INT_DISABLE(pDrvCtrl)                                       
  174.     {                                                                   
  175.     IMPORT STATUS sysLanIntDisable();                                   
  176.     sysLanIntDisable(pDrvCtrl->ilevel);                                 
  177.     }
  178. #endif /*SYS_INT_DISABLE*/
  179. #define NET_BUF_ALLOC()                                                 
  180.     netClusterGet (pDrvCtrl->end.pNetPool, pDrvCtrl->pClPoolId)
  181. #define NET_TO_SH7615END_BUF(netBuf)                                    
  182.     (((UINT32) (netBuf) + SH7615END_BD_ALIGN - 1)                       
  183.       & ~(SH7615END_BD_ALIGN - 1))
  184.  
  185. #define NET_BUF_FREE(pBuf)                                              
  186.     netClFree (pDrvCtrl->end.pNetPool, pBuf)
  187.  
  188. #define NET_MBLK_ALLOC()                                                
  189.     mBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT, MT_DATA)
  190.  
  191. #define NET_MBLK_FREE(pMblk)                                            
  192.     netMblkFree (pDrvCtrl->end.pNetPool, (M_BLK_ID)pMblk)
  193.  
  194. #define NET_CL_BLK_ALLOC()                                              
  195.     clBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT)
  196.  
  197. #define NET_CL_BLK_FREE(pClblk)                                         
  198.     clBlkFree (pDrvCtrl->end.pNetPool, (CL_BLK_ID)pClBlk)
  199.  
  200. #define NET_MBLK_BUF_FREE(pMblk)                                        
  201.     netMblkClFree ((M_BLK_ID)pMblk)
  202.   
  203. #define NET_MBLK_CL_JOIN(pMblk, pClBlk)                                 
  204.     netMblkClJoin ((pMblk), (pClBlk))
  205.  
  206. #define NET_CL_BLK_JOIN(pClBlk, pBuf, len)                              
  207.     netClBlkJoin ((pClBlk), (pBuf), (len), NULL, 0, 0, 0)
  208. #ifndef SYS_ENET_ADDR_GET
  209. #define SYS_ENET_ADDR_GET(pDrvCtrl, pAddress)                           
  210.     {                                                                   
  211.     IMPORT STATUS sysEnetAddrGet (int, char*);                          
  212.     sysEnetAddrGet (pDrvCtrl->unit, pAddress);                          
  213.     }
  214. #endif /* SYS_ENET_ADDR_GET */
  215. #define SH7615END_REG_READ(regAddr, value)                              
  216.     ((value) = (* (volatile UINT32 *) (regAddr)))
  217.  
  218. #define SH7615END_REG_WRITE(regAddr, value)                             
  219.     ((* (volatile UINT32 *) (regAddr)) = ((UINT32) value))
  220. #define SH7615END_BIT_SET(reg, val)                                     
  221.     {                                                                   
  222.     UINT32 temp = 0;                                                    
  223.     SH7615END_REG_READ(reg, temp);                                      
  224.     SH7615END_REG_WRITE((reg), temp | (val));                           
  225.     }
  226.    
  227. #define SH7615END_BIT_CLR(reg, val)                                     
  228.     {                                                                   
  229.     UINT32 temp = 0;                                                    
  230.     SH7615END_REG_READ(reg, temp);                                      
  231.     SH7615END_REG_WRITE((reg), temp & ~(val));                          
  232.     }
  233. /* DRV_CTRL flags access macros */
  234. #define DRV_FLAGS_SET(setBits)                                          
  235.     (pDrvCtrl->flags |= (setBits))
  236.  
  237. #define DRV_FLAGS_ISSET(setBits)                                        
  238.     (pDrvCtrl->flags & (setBits))
  239.  
  240. #define DRV_FLAGS_CLR(clrBits)                                          
  241.     (pDrvCtrl->flags &= ~(clrBits))
  242.  
  243. #define DRV_FLAGS_GET()                                                 
  244.     (pDrvCtrl->flags)
  245. #define END_FLAGS_ISSET(pEnd, setBits)                                  
  246.     ((pEnd)->flags & (setBits))
  247. /* A shortcut for getting the hardware address from the MIB II stuff. */
  248. #define END_HADDR(pEnd)                                                 
  249.     ((pEnd)->mib2Tbl.ifPhysAddress.phyAddress)
  250. #define END_HADDR_LEN(pEnd)                                             
  251.     ((pEnd)->mib2Tbl.ifPhysAddress.addrLength)
  252. /* Cache related macros */
  253. #define SH7615END_CACHE_FLUSH(address, len)                             
  254.     cacheFlush(DATA_CACHE, (address), (len))
  255.  
  256. #define SH7615END_CACHE_INVALIDATE(address, len)                        
  257.     cacheInvalidate (DATA_CACHE, (address), (len))
  258. /* DEBUG MACROS */
  259. #ifdef DRV_DEBUG
  260. #undef  LOCAL
  261. #define LOCAL
  262. #define DRV_DEBUG_OFF 0x0000
  263. #define DRV_DEBUG_RX 0x0001
  264. #define DRV_DEBUG_TX 0x0002
  265. #define DRV_DEBUG_INT 0x0004
  266. #define DRV_DEBUG_POLL (DRV_DEBUG_POLL_RX | DRV_DEBUG_POLL_TX)
  267. #define DRV_DEBUG_POLL_RX 0x0008
  268. #define DRV_DEBUG_POLL_TX 0x0010
  269. #define DRV_DEBUG_LOAD 0x0020
  270. #define DRV_DEBUG_IOCTL 0x0040
  271. #define DRV_DEBUG_POLL_REDIR 0x10000
  272. #define DRV_DEBUG_LOG_NVRAM 0x20000
  273. #define DRV_DEBUG_PHY 0x40000
  274.      
  275. int sh7615EndDebug = 0x40000;
  276. int sh7615EndRfcof = 0;
  277. int sh7615EndEci = 0;
  278. int sh7615EndTc = 0;
  279. int sh7615EndTde = 0;
  280. int sh7615EndTfuf = 0;
  281. int sh7615EndFr = 0;
  282. int sh7615EndRde = 0;
  283. int sh7615EndRfof = 0;
  284. int sh7615EndItf = 0;
  285. int sh7615EndCnd = 0;
  286. int sh7615EndDlc = 0;
  287. int sh7615EndCd = 0;
  288. int sh7615EndTro = 0;
  289. int sh7615EndRmaf = 0;
  290. int sh7615EndRrf = 0;
  291. int sh7615EndRtlf = 0;
  292. int sh7615EndRtsf = 0;
  293. int sh7615EndPre = 0;
  294. int sh7615EndCerf = 0;
  295. int sh7615EndTfe = 0;
  296. /* globals for easy access */
  297. CL_POOL_ID  sh7615ClPool;
  298. NET_POOL_ID sh7615NetPoolId;
  299. DRV_CTRL *  pShEnd;
  300. #define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6)                        
  301. if (sh7615EndDebug & FLG)                                        
  302.             logMsg(X0, X1, X2, X3, X4, X5, X6);
  303. #define DRV_PRINT(FLG,X)                                                
  304. if (sh7615EndDebug & FLG) printf X;
  305. #else /*DRV_DEBUG*/
  306. #define DRV_LOG(DBG_SW, X0, X1, X2, X3, X4, X5, X6)
  307. #define DRV_PRINT(DBG_SW,X)
  308. #endif /*DRV_DEBUG*/
  309. /* LOCALS */
  310. /* forward static functions */
  311. LOCAL void sh7615EndReset (DRV_CTRL *pDrvCtrl);    
  312. LOCAL void sh7615EndInt (DRV_CTRL *pDrvCtrl);
  313. LOCAL void sh7615EndRcvIntHandle (DRV_CTRL *pDrvCtrl);
  314. LOCAL STATUS sh7615EndRecv (DRV_CTRL *pDrvCtrl, SH7615_RD * pRxD );
  315. LOCAL void sh7615EndConfig (DRV_CTRL *pDrvCtrl);
  316. LOCAL void  sh7615EndModeSet (DRV_CTRL *pDrvCtrl);
  317. LOCAL STATUS sh7615EndParse (DRV_CTRL * pDrvCtrl, char * initString); 
  318. LOCAL STATUS sh7615EndMemInit (DRV_CTRL * pDrvCtrl);
  319. LOCAL void      sh7615EnetAddrGet (DRV_CTRL* pDrvCtrl, char* addr);
  320. LOCAL SH7615_RD * sh7615EndRxDGet (DRV_CTRL *pDrvCtrl);
  321. LOCAL SH7615_TD * sh7615EndTxDGet (DRV_CTRL *pDrvCtrl);
  322. LOCAL void      sh7615EndTxRingClean (DRV_CTRL *pDrvCtrl);
  323. LOCAL void      sh7615EndRestart (DRV_CTRL *pDrvCtrl);
  324. #ifdef INCLUDE_PHY
  325. LOCAL void  dp83843SingleBitWrite (int bitVal);
  326. #if 0  /* currently not used */
  327. LOCAL void  dp83843RegWrite (UINT16 regAddr, UINT16 regData);
  328. #endif
  329. LOCAL UINT16 dp83843RegRead (UINT16 regAddr);
  330. #endif
  331. /* END Specific interfaces. */
  332. END_OBJ*  sh7615EndLoad (char* initString);
  333. LOCAL STATUS sh7615EndUnload (DRV_CTRL* pDrvCtrl);
  334. LOCAL STATUS sh7615EndStart (DRV_CTRL* pDrvCtrl);
  335. LOCAL STATUS sh7615EndStop (DRV_CTRL* pDrvCtrl);
  336. LOCAL STATUS sh7615EndIoctl (DRV_CTRL* pDrvCtrl, int cmd, caddr_t data);
  337. LOCAL STATUS    sh7615EndSend (DRV_CTRL *pDrvCtrl, M_BLK *pMblk);
  338. LOCAL STATUS    sh7615EndMCastAddrAdd (DRV_CTRL *pDrvCtrl, char* pAddress);
  339. LOCAL STATUS    sh7615EndMCastAddrDel (DRV_CTRL *pDrvCtrl, char* pAddress);
  340. LOCAL STATUS    sh7615EndMCastAddrGet (DRV_CTRL *pDrvCtrl,
  341.                                        MULTI_TABLE *pTable);
  342. LOCAL STATUS    sh7615EndPollSend (DRV_CTRL *pDrvCtrl, M_BLK *pMblk);
  343. LOCAL STATUS    sh7615EndPollReceive (DRV_CTRL *pDrvCtrl, M_BLK *pMblk);
  344. LOCAL STATUS    sh7615EndPollStart (DRV_CTRL *pDrvCtrl);
  345. LOCAL STATUS    sh7615EndPollStop (DRV_CTRL *pDrvCtrl);
  346. /*
  347.  * Declare our function table.  This is static across all driver
  348.  * instances.
  349.  */
  350. LOCAL NET_FUNCS sh7615EndFuncTable =
  351.     {
  352.     (FUNCPTR) sh7615EndStart, /* Function to start the device. */
  353.     (FUNCPTR) sh7615EndStop, /* Function to stop the device. */
  354.     (FUNCPTR) sh7615EndUnload, /* Unloading function for the driver. */
  355.     (FUNCPTR) sh7615EndIoctl, /* Ioctl function for the driver. */
  356.     (FUNCPTR) sh7615EndSend,            /* send func. */
  357.     (FUNCPTR) sh7615EndMCastAddrAdd,    /* multicast add func. */
  358.     (FUNCPTR) sh7615EndMCastAddrDel,    /* multicast delete func. */
  359.     (FUNCPTR) sh7615EndMCastAddrGet,    /* multicast get fun. */
  360.     (FUNCPTR) sh7615EndPollSend,        /* polling send func. */
  361.     (FUNCPTR) sh7615EndPollReceive,     /* polling receive func. */
  362.     endEtherAddressForm,         /* put address info into a NET_BUFFER */
  363.     (FUNCPTR) endEtherPacketDataGet,  /* get pointer to data in NET_BUFFER */
  364.     (FUNCPTR) endEtherPacketAddrGet  /* Get packet addresses. */
  365.     };
  366. /*******************************************************************************
  367. *
  368. * sh7615EndLoad - initialize the driver and device
  369. *
  370. * This routine initializes the driver and the device to the operational state.
  371. * All of the device specific parameters are passed in the initString.
  372. *
  373. * The string contains the target specific parameters like this:
  374. *  "ivec:ilevel:numRds:numTds:phyDefMode:userFlags"
  375. *
  376. * RETURNS: An END object pointer or NULL on error.
  377. */
  378. END_OBJ* sh7615EndLoad
  379.     (
  380.     char * initString /* String to be parsed by the driver. */
  381.     )
  382.     {
  383.     DRV_CTRL * pDrvCtrl;
  384.     DRV_LOG (DRV_DEBUG_LOAD, "Loading sh7615End...n", 1, 2, 3, 4, 5, 6);
  385.     if (initString == NULL)
  386.         return (NULL);
  387.  
  388.     if (initString[0] == EOS)
  389.         {
  390.         bcopy((char *)SH7615END_DEV_NAME, initString, SH7615END_DEV_NAME_LEN);
  391.         return (0);
  392.         }
  393.     /* Allocate a control structure for this device */
  394.     pDrvCtrl = (DRV_CTRL *)calloc (sizeof (DRV_CTRL), 1);
  395.     if (pDrvCtrl == NULL)
  396.         {
  397.         printf ("%s - Failed to allocate control structuren",
  398.                 SH7615END_DEV_NAME );
  399.         return (NULL);
  400.         }
  401.     /* parse the init string, filling in the device structure */
  402.     if (sh7615EndParse (pDrvCtrl, initString) == ERROR)
  403.         goto errorExit;
  404.     /* Ask the BSP to provide the ethernet address. */
  405.     sh7615EnetAddrGet (pDrvCtrl, (char*) &(pDrvCtrl->enetAddr));
  406.     DRV_LOG (DRV_DEBUG_LOAD, "ENET Addr: %x:%x:%x:%x:%x:%x n",
  407.              pDrvCtrl->enetAddr[0], pDrvCtrl->enetAddr[1],
  408.              pDrvCtrl->enetAddr[2], pDrvCtrl->enetAddr[3],
  409.              pDrvCtrl->enetAddr[4], pDrvCtrl->enetAddr[5]);
  410.     /* initialize some flags */
  411.  
  412.     pDrvCtrl->loaded = TRUE;
  413.     /* initialize the END and MIB2 parts of the structure */
  414.     /*
  415.      * The M2 element must come from m2Lib.h 
  416.      * This sh7615End is set up for a DIX type ethernet device.
  417.      */
  418.     
  419.     if (END_OBJ_INIT (&pDrvCtrl->end, (DEV_OBJ *)pDrvCtrl, SH7615END_DEV_NAME, 
  420.                       pDrvCtrl->unit, &sh7615EndFuncTable,
  421.                       "Hitachi SH7615 Enhanced Network Driver.") == ERROR
  422.      || END_MIB_INIT (&pDrvCtrl->end, M2_ifType_ethernet_csmacd,
  423.                       &pDrvCtrl->enetAddr[0], 6, ETHERMTU, SH7615END_SPEED)
  424.     == ERROR)
  425.         goto errorExit;
  426.     pDrvCtrl->flags = 0; 
  427.     /* Perform memory allocation/distribution */
  428.     if (sh7615EndMemInit (pDrvCtrl) == ERROR)
  429. goto errorExit;
  430.     /* set the End flags to indicate readiness */
  431.     END_OBJ_READY (&pDrvCtrl->end, 
  432.                          (IFF_NOTRAILERS | IFF_MULTICAST | IFF_BROADCAST));
  433.     DRV_LOG (DRV_DEBUG_LOAD, "Done loading sh7615end...", 1, 2, 3, 4, 5, 6);
  434. #ifdef DRV_DEBUG
  435.     pShEnd = pDrvCtrl;
  436. #endif     
  437.     
  438.     return (&pDrvCtrl->end);
  439. errorExit:
  440.     sh7615EndUnload (pDrvCtrl); 
  441.     free ((char *)pDrvCtrl);
  442.     return NULL;
  443.     }
  444. /******************************************************************************
  445. *
  446. * sh7615EndUnload - unload a driver from the system
  447. *
  448. * This function first brings down the device, and then frees any
  449. * stuff that was allocated by the driver in the load function.
  450. *
  451. * RETURNS: OK or ERROR.
  452. */
  453. LOCAL STATUS sh7615EndUnload
  454.     (
  455.     DRV_CTRL* pDrvCtrl /* device to be unloaded */
  456.     )
  457.     {
  458.  
  459.     DRV_LOG (DRV_DEBUG_LOAD, "EndUnloadn", 0, 0, 0, 0, 0, 0);
  460.     if (pDrvCtrl == NULL)
  461.         return (ERROR);
  462.  
  463.     pDrvCtrl->loaded = FALSE;
  464.  
  465.     END_OBJECT_UNLOAD (&pDrvCtrl->end);
  466.     /* free allocated shared memory */
  467.     if (pDrvCtrl->memBase != NULL)
  468. cacheDmaFree (pDrvCtrl->memBase);
  469.     /* free allocated memory if necessary */
  470.  
  471.     if ((pDrvCtrl->pMBlkArea) != NULL)
  472.         free (pDrvCtrl->pMBlkArea);
  473.     /* REVISIT - what about clusters? */
  474.     cfree ((char *) pDrvCtrl);
  475.     return (OK);
  476.     }
  477. /*******************************************************************************
  478. *
  479. * sh7615EndParse - parse the init string
  480. *
  481. * Parse the input string.  Fill in values in the driver control structure.
  482. *
  483. * The muxLib.o module automatically prepends the unit number to the user's
  484. * initialization string from the BSP (configNet.h).
  485. *
  486. *
  487. * RETURNS: OK or ERROR for invalid arguments.
  488. */
  489. LOCAL STATUS sh7615EndParse
  490.     (
  491.     DRV_CTRL * pDrvCtrl, /* device pointer */
  492.     char * initString /* information string */
  493.     )
  494.     {
  495.     char* tok;
  496.     char* pHolder = NULL;
  497.     /* Parse the initString */
  498.     /* Unit number. (from muxLib.o) */
  499.     tok = strtok_r (initString, ":", &pHolder);
  500.     if (tok == NULL)
  501. return ERROR;
  502.     pDrvCtrl->unit = atoi (tok);
  503.     /* Get various driver configuration values */
  504.     tok = strtok_r (NULL, ":", &pHolder);
  505.     if (tok == NULL)
  506. return ERROR;
  507.     pDrvCtrl->ivec = atoi (tok);
  508.     tok = strtok_r (NULL, ":", &pHolder);
  509.     if (tok == NULL)
  510. return ERROR;
  511.     pDrvCtrl->ilevel = atoi (tok);
  512.     tok = strtok_r (NULL, ":", &pHolder);
  513.     if (tok == NULL)
  514.         return ERROR;
  515.     pDrvCtrl->numTds = strtoul (tok, NULL, 16);
  516.  
  517.     tok = strtok_r (NULL, ":", &pHolder);
  518.     if (tok == NULL)
  519.         return ERROR;
  520.     pDrvCtrl->numRds = strtoul (tok, NULL, 16);
  521.     /* PHY options (phyDefMode) currently not used */
  522.     tok = strtok_r (NULL, ":", &pHolder);
  523.     if (tok == NULL)
  524.         return ERROR;
  525.     tok = strtok_r (NULL, ":", &pHolder);
  526.     if (tok == NULL)
  527.         return ERROR;
  528.     pDrvCtrl->userFlags = strtoul (tok, NULL, 16);
  529.     /* Use default values for invalid settings */
  530.     if (!pDrvCtrl->numTds || pDrvCtrl->numTds <= 2)
  531.         {
  532.         DRV_FLAGS_SET (SH7615END_INV_TBD_NUM);
  533.         pDrvCtrl->numTds = SH7615END_TBD_DEF_NUM;
  534.         }
  535.  
  536.     if (!pDrvCtrl->numRds || pDrvCtrl->numRds <= 2)
  537.         {
  538.         DRV_FLAGS_SET (SH7615END_INV_RBD_NUM);
  539.         pDrvCtrl->numRds = SH7615END_RBD_DEF_NUM;
  540.         }
  541.     DRV_LOG (DRV_DEBUG_LOAD, "Processed all arugmentsn", 1, 2, 3, 4, 5, 6);
  542.     return OK;
  543.     }
  544. /*******************************************************************************
  545. *
  546. * sh7615EndMemInit - initialize memory for the chip
  547. *
  548. * This routine sets up memory required by the driver. It is highly specific 
  549. * to the device.
  550. *
  551. * RETURNS: OK or ERROR.
  552. */
  553. LOCAL STATUS sh7615EndMemInit
  554.     (
  555.     DRV_CTRL * pDrvCtrl /* device to be initialized */
  556.     )
  557.     {
  558.     SH7615_RD * pRxD;
  559.     SH7615_TD * pTxD;
  560.     char * pBuf;
  561.     int ix;
  562.     int sz;
  563.     M_CL_CONFIG mclBlkConfig = {0, 0, NULL, 0};
  564.                                         /* cluster blocks configuration */
  565.     CL_DESC     clDesc = {SH7615END_BUFSIZ, 0, NULL, 0};
  566.                                         /* cluster blocks config table */
  567.     /* Establish size of shared memory region we require */
  568.  
  569.     DRV_LOG (DRV_DEBUG_LOAD, "MemInit n", 0, 0, 0, 0, 0, 0);
  570.     /* Establish a region of shared memory - allow for 16 byte align */
  571.     sz = (((pDrvCtrl->numRds + 1) * SH7615END_RBD_SZ) +
  572.           ((pDrvCtrl->numTds + 1) * SH7615END_TBD_SZ));
  573.     /* this driver can't handle write incoherent caches */
  574.  
  575.     if (!CACHE_DMA_IS_WRITE_COHERENT ())
  576.         {
  577.         DRV_LOG (DRV_DEBUG_LOAD, "sh7615EndMemInit: shared
  578.                                    memory not cache coherentn",
  579.                                    1, 2, 3, 4, 5, 6);
  580.         return (ERROR);
  581.         }
  582.     /* cacheDmaMalloc returns CACHE_ALIGN_SIZE aligned and rounded
  583.      * non-cacheable buffer. So, there is no need to flush and invalidate
  584.      * descriptor buffers in this driver.
  585.      */
  586.     pDrvCtrl->memBase = (char *) cacheDmaMalloc (sz);
  587.     if (pDrvCtrl->memBase == NULL)
  588.        {
  589.         DRV_LOG (DRV_DEBUG_LOAD, "%s%d - system memory unavailablen",
  590.                  (int)SH7615END_DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6);
  591.         return (ERROR);
  592.         }
  593.     pDrvCtrl->memSize = sz;
  594.     /* zero the shared memory */
  595.     bzero (pDrvCtrl->memBase, (int) pDrvCtrl->memSize);
  596.     /* ensure 16 byte alignment - device requirement */
  597.     pDrvCtrl->rxRing = (SH7615_RD *) NET_TO_SH7615END_BUF (pDrvCtrl->memBase);
  598.     /* carve Tx memory structure */
  599.     pDrvCtrl->txRing = (SH7615_TD *) (pDrvCtrl->rxRing + pDrvCtrl->numRds);
  600.     /* Initialize net buffer pool for tx/rx buffers */
  601.     clDesc.clNum    = pDrvCtrl->numRds + pDrvCtrl->numTds + NUM_LOAN;
  602.     mclBlkConfig.mBlkNum  = pDrvCtrl->numRds * 4;
  603.     mclBlkConfig.clBlkNum = clDesc.clNum;
  604.     mclBlkConfig.memSize = mclBlkConfig.mBlkNum * (MSIZE + sizeof (long)) +
  605.                            mclBlkConfig.clBlkNum * (CL_BLK_SZ + sizeof(long));
  606.     mclBlkConfig.memArea = (char *) memalign (MBLK_ALIGNMENT, 
  607.       mclBlkConfig.memSize);
  608.     if (mclBlkConfig.memArea == NULL)
  609. return (ERROR);
  610.     /* store the pointer to the mBlock area */
  611.     pDrvCtrl->pMBlkArea = mclBlkConfig.memArea;
  612.     pDrvCtrl->mBlkSize = mclBlkConfig.memSize;
  613.     /* Calculate the memory size of all the clusters. */
  614.     clDesc.clSize = SH7615END_BUFSIZ;
  615.     clDesc.memSize = clDesc.clNum * (clDesc.clSize + sizeof(int));
  616.     clDesc.memArea = (char *) memalign (CL_ALIGNMENT, clDesc.memSize);
  617.     if (clDesc.memArea == NULL)
  618.         {
  619.         DRV_LOG (DRV_DEBUG_LOAD, "system memory unavailablen",
  620.                      1, 2, 3, 4, 5, 6);
  621.         return (ERROR);
  622.         }
  623.     /* store the pointer to the clBlock area - for show purposes */
  624.  
  625.     pDrvCtrl->pClBlkArea = clDesc.memArea;
  626.     pDrvCtrl->clBlkSize = clDesc.memSize;
  627.     /* Allocate and initialize the memory pool. */
  628.     
  629.     if ((pDrvCtrl->end.pNetPool = malloc (sizeof(NET_POOL))) == NULL)
  630.         return (ERROR);
  631.     if (netPoolInit(pDrvCtrl->end.pNetPool, &mclBlkConfig,
  632.                     &clDesc, 1, NULL) == ERROR)
  633.         {
  634.         DRV_LOG (DRV_DEBUG_LOAD, "Could not initialize net poolsn",
  635. 1, 2, 3, 4, 5, 6);
  636.         return (ERROR);
  637.         }
  638.     /* Save the cluster pool id */
  639.     pDrvCtrl->pClPoolId = netClPoolIdGet (pDrvCtrl->end.pNetPool,
  640.   SH7615END_BUFSIZ, FALSE);
  641.     if (pDrvCtrl->pClPoolId == NULL)
  642.         return (ERROR);
  643. #ifdef DRV_DEBUG
  644.     sh7615NetPoolId = pDrvCtrl->end.pNetPool;
  645.     sh7615ClPool  = pDrvCtrl->pClPoolId;
  646. #endif
  647.     /* Clear all indices */
  648.     pDrvCtrl->rxIndex=0;
  649.     pDrvCtrl->txIndex=0;
  650.     pDrvCtrl->txDiIndex=0;
  651.     pDrvCtrl->txCleaning = FALSE;
  652.     pDrvCtrl->rxHandling = FALSE;
  653.     pDrvCtrl->txBlocked = FALSE;
  654.     /* Setup the receive ring */
  655.     pRxD = pDrvCtrl->rxRing;
  656.     for (ix = 0; ix < pDrvCtrl->numRds; ix++, pRxD++)
  657.         {
  658.         pBuf = NET_BUF_ALLOC();
  659.         if (pBuf == NULL)
  660.             {
  661.     pDrvCtrl->lastError.errCode = END_ERR_NO_BUF;
  662.     muxError (&pDrvCtrl->end, &pDrvCtrl->lastError);
  663.             DRV_LOG (DRV_DEBUG_LOAD, "Could not get a buffern",
  664.                      1, 2, 3, 4, 5, 6);
  665.             return (ERROR);
  666.             }
  667.         pRxD->rDesc0 = RD0_OWN;                      /* chip owns the buffer */
  668.         pRxD->rDesc1 = SH7615END_BUFSIZ << 16;       /* max frame size */
  669.         pRxD->rDesc2 = NET_TO_SH7615END_BUF (pBuf);  /* buffer address */
  670.         pRxD->rDesc3 = (UINT32) pBuf;                /* The real cluster address */
  671.  
  672.         if (ix == (pDrvCtrl->numRds - 1))    /* if its is last one */
  673.             pRxD->rDesc0 |= RD0_RDL;         /* end of receive ring */
  674.         }
  675.     /* Setup the transmit ring */
  676.     pTxD = pDrvCtrl->txRing;
  677.     for (ix = 0; ix < pDrvCtrl->numTds; ix++, pTxD++)
  678.         {
  679.         /* empty -- no buffers at this time -- owner is host */
  680.         pTxD->tDesc0 = 0;
  681.         pTxD->tDesc1 = 0;
  682.         pTxD->tDesc2 = 0;
  683.         pTxD->tDesc3 = 0;
  684.  
  685.         if (ix == (pDrvCtrl->numTds - 1))    /* if its is last one */
  686.             pTxD->tDesc0 |= TD0_TDL;         /* end of transmit ring */
  687.         }
  688.     DRV_LOG (DRV_DEBUG_LOAD, "Memory setup completen", 1, 2, 3, 4, 5, 6);
  689.     return OK;
  690.     }
  691. /***************************************************************************
  692. *
  693. * sh7615EndRestart - restart the device
  694. *
  695. * Restarts the device after cleaning up the transmit and receive queues. This
  696. * routine should be called only after sh7615EndStop().
  697. *
  698. * RETURNS: OK or ERROR
  699. */
  700. LOCAL void sh7615EndRestart
  701.     (
  702.     DRV_CTRL *pDrvCtrl
  703.     )
  704.     {
  705.     SH7615_TD  *pTxD = pDrvCtrl->txRing;
  706.     FREE_BUF *pFreeBuf = pDrvCtrl->freeBuf;
  707.     SH7615_RD *pRxD;
  708.     int count;
  709.     
  710.     DRV_LOG (DRV_DEBUG_LOAD, "%s%d - restarting device.n",
  711.             (int)SH7615END_DEV_NAME, pDrvCtrl->unit, 0, 0, 0, 0);
  712.     
  713.     /* cleanup the tx and rx queues */
  714.     sh7615EndTxRingClean (pDrvCtrl);
  715.     while ((pRxD = sh7615EndRxDGet (pDrvCtrl)) != NULL)
  716. sh7615EndRecv (pDrvCtrl, pRxD);
  717.     /* drop rest of the queued tx packets */
  718.     for (count=pDrvCtrl->numTds; count > 0; count--, pTxD++, pFreeBuf++)
  719.         {
  720. /* Free buffers */
  721.         if (pFreeBuf->pClBuf != NULL)
  722.             {
  723.             NET_BUF_FREE(pFreeBuf->pClBuf);
  724.             pFreeBuf->pClBuf = NULL;
  725.             }
  726. /* These never had the chance to be sent */
  727.         if (pTxD->tDesc0 & TD0_OWN)
  728.             {
  729.             END_OBJ     *pEndObj = &pDrvCtrl->end;
  730.  
  731.             END_ERR_ADD (pEndObj, MIB2_OUT_ERRS, +1);
  732.             END_ERR_ADD (pEndObj, MIB2_OUT_UCAST, -1);
  733.             }
  734. /* Mark descriptors free */
  735. #if 0
  736. pTxD->tDesc0 &= TD0_CLEAR_ERRORS_N_STATS;
  737. #else
  738. /* Mark descriptors free */
  739.         pTxD->tDesc0 = 0;
  740.         pTxD->tDesc1 = 0;
  741.         pTxD->tDesc2 = 0;
  742.         pTxD->tDesc3 = 0;
  743.  
  744.         if (count == 1) /* if it is last one */
  745.             pTxD->tDesc0 |= TD0_TDL; /* end of transmit ring */
  746. #endif
  747.         }
  748.     /* Start the device */
  749.     sh7615EndStart (pDrvCtrl);
  750.     }
  751. /*******************************************************************************
  752. *
  753. * sh7615EndStart - start the device
  754. *
  755. * This function calls BSP functions to connect interrupts and start the
  756. * device running in interrupt mode. The driver must have already been loaded 
  757. * with the sh7615EndLoad() routine.
  758. *
  759. * RETURNS: OK or ERROR
  760. *
  761. */
  762. LOCAL STATUS sh7615EndStart
  763.     (
  764.     DRV_CTRL * pDrvCtrl /* device ID */
  765.     )
  766.     {
  767.     STATUS  result;
  768.     DRV_LOG (DRV_DEBUG_LOAD, "Starting shend n", 0, 0, 0, 0, 0, 0);
  769.     /* must have been loaded */
  770.  
  771.     if (!pDrvCtrl->loaded)
  772.         return (ERROR);
  773.     /* Reset the device */
  774.     sh7615EndReset (pDrvCtrl);
  775.     /* Clear all indices */
  776.     pDrvCtrl->rxIndex = 0;
  777.     pDrvCtrl->txIndex = 0;
  778.     pDrvCtrl->txDiIndex = 0;
  779.  
  780.     pDrvCtrl->txCleaning = FALSE;
  781.     pDrvCtrl->rxHandling = FALSE;
  782.     pDrvCtrl->txBlocked = FALSE;
  783.     /* Configure and start the device */
  784.     sh7615EndConfig (pDrvCtrl);
  785.     /* Connect the interrupt handler */
  786.     SYS_INT_CONNECT (pDrvCtrl, sh7615EndInt, (int)pDrvCtrl, &result);
  787.     if (result == ERROR)
  788. return ERROR;
  789.     /* mark the interface -- up */
  790.     END_FLAGS_SET (&pDrvCtrl->end, (IFF_UP | IFF_RUNNING));
  791.     /* Enable LAN interrupts */
  792.     SYS_INT_ENABLE (pDrvCtrl); 
  793.     return (OK);
  794.     }
  795. /*******************************************************************************
  796. *
  797. * sh7615EndStop - stop the device
  798. *
  799. * This function calls BSP functions to disconnect interrupts and stop
  800. * the device from operating in interrupt mode.
  801. *
  802. * RETURNS: OK or ERROR.
  803. */
  804. LOCAL STATUS sh7615EndStop
  805.     (
  806.     DRV_CTRL * pDrvCtrl /* device to be stopped */
  807.     )
  808.     {
  809.     STATUS  result = OK;
  810.     /* mark the interface -- down */
  811.     END_FLAGS_CLR (&pDrvCtrl->end, IFF_UP | IFF_RUNNING);
  812.     /* stop transmit and receive */
  813.     SH7615END_BIT_CLR(ETHERC_ECMR, ECMR_TE);    
  814.     SH7615END_BIT_CLR(ETHERC_ECMR, ECMR_RE);   
  815.  
  816.     /* Disable LAN interrupts */
  817.     SYS_INT_DISABLE (pDrvCtrl);
  818.     SYS_INT_DISCONNECT (pDrvCtrl, sh7615EndInt, (int)pDrvCtrl, &result);
  819.     return (result);
  820.     }
  821. /*******************************************************************************
  822. *
  823. * sh7615EndInt - handle controller interrupt
  824. *
  825. * This routine is called at interrupt level in response to an interrupt from
  826. * the controller.
  827. *
  828. * RETURNS: N/A.
  829. */
  830. LOCAL void sh7615EndInt
  831.     (
  832.     DRV_CTRL * pDrvCtrl /* interrupting device */
  833.     )
  834.     {
  835.     UINT32 status;
  836.     /* Read the device status register */
  837.     SH7615END_REG_READ (E_DMAC_EESR, status);
  838.     /* if not one of our interrupts, exit */
  839.     if ((status & pDrvCtrl->intrMask) == 0)
  840.         {
  841.         return;
  842.         }
  843.     /*
  844.      * read is not destructive, so, lets clear the sources by writing
  845.      * the status back. This is safe to do since writing a 0 value does
  846.      * not clear the bit. New sources may have come in, but they'll be
  847.      * latched into the interrupt controller and caught when we exit here.
  848.      */
  849.     SH7615END_REG_WRITE (E_DMAC_EESR, status);
  850.     /* Handle link status change */
  851.     if ((status & EESR_ECI) != 0)
  852. {
  853. UINT32 ecsr;
  854. SH7615END_REG_READ (ETHERC_ECSR, ecsr);
  855. SH7615END_REG_WRITE (ETHERC_ECSR, ecsr);
  856. if ((ecsr & ECSR_LCHNG) != 0)
  857.     {
  858.             DRV_LOG (DRV_DEBUG_INT, "%s%d - link status changen",
  859.                      (int)SH7615END_DEV_NAME, pDrvCtrl->unit, 0, 0, 0, 0);
  860.     
  861.     sh7615EndStop (pDrvCtrl);
  862.     netJobAdd ((FUNCPTR)sh7615EndRestart, (int)pDrvCtrl, 0, 0, 0, 0);
  863.     return;
  864.     }
  865. }
  866.     /* Handle received packets */
  867.     
  868.     if ((status & EESR_FR) && (!pDrvCtrl->rxHandling)) 
  869.         {
  870.         /* DRV_LOG (DRV_DEBUG_INT, "Recieve Int!! n", 0, 0, 0, 0, 0, 0); */
  871.         if (netJobAdd ((FUNCPTR)sh7615EndRcvIntHandle, 
  872.                        (int)pDrvCtrl, 0, 0, 0, 0) == OK)
  873.             {
  874.             /*
  875.      * prevent additional scheduling of task level recv handling due
  876.              * to new recv ints that may have been latched since we entered
  877.              * here.
  878.              */
  879.             pDrvCtrl->rxHandling = TRUE;
  880.             /*
  881.      * disable Rx ints - we've already got a handler scheduled so
  882.              * no need to come in here again. Note, that we may already have
  883.              * latched a recv int since we entered here and cleared the status
  884.              * bits above. the rxHandling will ensure that guy schedules no
  885.              * no more jobs.
  886.              */
  887.             SH7615END_BIT_CLR (E_DMAC_EESIPR, EESIPR_FRIP);
  888.             }
  889.         }
  890. #ifdef DRV_DEBUG
  891.     if (status & EESR_RFCOF)
  892.         sh7615EndRfcof++;
  893.     if (status & EESR_ECI)
  894.         sh7615EndEci++;
  895.     if (status & EESR_TC)
  896.         sh7615EndTc++;
  897.     if (status & EESR_TDE)
  898.         sh7615EndTde++;
  899.     if (status & EESR_TFUF)
  900.         sh7615EndTfuf++;
  901.     if (status & EESR_FR)
  902.         sh7615EndFr++;
  903.     if (status & EESR_RDE)
  904.         sh7615EndRde++;
  905.     if (status & EESR_RFOF)
  906.         sh7615EndRfof++;
  907.     if (status & EESR_ITF)
  908.         sh7615EndItf++;
  909.     if (status & EESR_CND)
  910.         sh7615EndCnd++;
  911.     if (status & EESR_DLC)
  912.         sh7615EndDlc++;
  913.     if (status & EESR_CD)
  914.         sh7615EndCd++;
  915.     if (status & EESR_TRO)
  916.         sh7615EndTro++;
  917.     if (status & EESR_RMAF)
  918.         sh7615EndRmaf++;
  919.     if (status & EESR_RRF)
  920.         sh7615EndRrf++;
  921.     if (status & EESR_RTLF)
  922.         sh7615EndRtlf++;
  923.     if (status & EESR_RTSF)
  924.         sh7615EndRtsf++;
  925.     if (status & EESR_PRE)
  926.         sh7615EndPre++;
  927.     if (status & EESR_CERF)
  928.         sh7615EndCerf++;
  929. #endif
  930.     /* Cleanup TxRing */
  931.  
  932.     if ((status & EESR_TC) && (!pDrvCtrl->txCleaning))
  933. {
  934. DRV_LOG (DRV_DEBUG_INT, "Cleanup TxRing from Int() n", 0, 0, 0, 0, 0, 0);
  935. pDrvCtrl->txCleaning = TRUE;
  936.  
  937. netJobAdd ((FUNCPTR)sh7615EndTxRingClean, (int)pDrvCtrl, 0, 0, 0, 0);
  938. }
  939.     if (pDrvCtrl->txBlocked)
  940. {
  941. pDrvCtrl->txBlocked = FALSE;
  942. netJobAdd ((FUNCPTR)muxTxRestart, (int)&pDrvCtrl->end, 0, 0, 0, 0);
  943. }
  944.     }
  945. /*******************************************************************************
  946. *
  947. * sh7615EndRxDGet - get next receive descriptor
  948. *
  949. * Get next receive descriptor.  Returns NULL if none are ready.
  950. *
  951. * RETURNS: ptr to next packet, or NULL if none ready.
  952. */
  953. LOCAL SH7615_RD * sh7615EndRxDGet
  954.     (
  955.     DRV_CTRL * pDrvCtrl /* device structure */
  956.     )
  957.     {
  958.     SH7615_RD * pRxD = pDrvCtrl->rxRing + pDrvCtrl->rxIndex;
  959.  
  960.     /* check if the descriptor is owned by the chip. The chip will clear
  961.      * this bit once it has completed writing to the buffer.
  962.      */
  963.     if (pRxD->rDesc0 & RD0_OWN)
  964.         return NULL;
  965.     return pRxD;
  966.     }
  967. /*******************************************************************************
  968. *
  969. * sh7615EndTxDGet - get an available transmit descriptor
  970. *
  971. * Get next transmit descriptor.  Returns NULL if none are ready.
  972. *
  973. * RETURNS: an available transmit descriptor, otherwise NULL.
  974. */
  975.  
  976. LOCAL SH7615_TD * sh7615EndTxDGet
  977.     (
  978.     DRV_CTRL * pDrvCtrl
  979.     )
  980.     {
  981.     SH7615_TD * pTxD = pDrvCtrl->txRing + pDrvCtrl->txIndex;
  982.  
  983.     /* check if this descriptor is owned by the chip or is out of bounds */
  984.     if ((pTxD->tDesc0 & TD0_OWN) ||
  985.         (((pDrvCtrl->txIndex + 1) % pDrvCtrl->numTds) == pDrvCtrl->txDiIndex))
  986.         return (NULL);
  987.  
  988.     return pTxD;
  989.     }
  990. /*******************************************************************************
  991. *
  992. * sh7615EndTxRingClean - clean up processed tx descriptors
  993. *
  994. * This routine processes the transmit queue, freeing all transmitted
  995. * descriptors.
  996. *
  997. * RETURNS: None
  998. */
  999. LOCAL void sh7615EndTxRingClean
  1000.     (
  1001.     DRV_CTRL * pDrvCtrl
  1002.     )
  1003.     {
  1004.     SH7615_TD * pTxD;
  1005.     pDrvCtrl->txCleaning = TRUE;
  1006.  
  1007.     while (pDrvCtrl->txDiIndex != pDrvCtrl->txIndex)
  1008.         {
  1009.         pTxD = pDrvCtrl->txRing + pDrvCtrl->txDiIndex;
  1010.  
  1011. /* All handled, break from the loop */
  1012.         if (pTxD->tDesc0 & TD0_OWN)
  1013.             break;
  1014.  
  1015.         /* free the buffer */
  1016.  
  1017.         if (pDrvCtrl->freeBuf[pDrvCtrl->txDiIndex].pClBuf != NULL)
  1018.             {
  1019.             NET_BUF_FREE(pDrvCtrl->freeBuf[pDrvCtrl->txDiIndex].pClBuf);
  1020.             pDrvCtrl->freeBuf[pDrvCtrl->txDiIndex].pClBuf = NULL;
  1021.             }
  1022.  
  1023.         pDrvCtrl->txDiIndex =  (pDrvCtrl->txDiIndex + 1) % pDrvCtrl->numTds;
  1024.         /* count collisions */
  1025. #if 0
  1026.         if (! (pTxD->tDesc0 & TD0_CD))
  1027.             END_ERR_ADD (pEndObj, MIB2_COLLISIONS,
  1028.                          SH7615END_REG_READ (ETHERC_CDCR));
  1029. #endif
  1030.  
  1031.         if (pTxD->tDesc0 & TD0_TFE)
  1032.             {
  1033.             END_OBJ     *pEndObj = &pDrvCtrl->end;
  1034.  
  1035.             END_ERR_ADD (pEndObj, MIB2_OUT_ERRS, +1);
  1036.             END_ERR_ADD (pEndObj, MIB2_OUT_UCAST, -1);
  1037.  
  1038. #ifdef DRV_DEBUG
  1039.             /* check for no carrier */
  1040.             if (pTxD->tDesc0 & (TD0_CND | TD0_DLC))
  1041.                 {
  1042.                 logMsg ("%s%d - no carriern",
  1043.                         (int)SH7615END_DEV_NAME, pDrvCtrl->unit, 0, 0, 0, 0);
  1044.                 }
  1045.     sh7615EndTfe++;
  1046. #endif /* DRV_DEBUG */
  1047.             }
  1048.         /* clear errors and stats but don't touch TDL bit */
  1049.  
  1050.         pTxD->tDesc0 &= TD0_CLEAR_ERRORS_N_STATS;
  1051.         }
  1052.  
  1053.     pDrvCtrl->txCleaning = FALSE;
  1054.  
  1055.     return;
  1056.     }
  1057. /*******************************************************************************
  1058. *
  1059. * sh7615EndRecv - process the next incoming packet
  1060. *
  1061. * Handle one incoming packet.  The packet is checked for errors.
  1062. *
  1063. * RETURNS: N/A.
  1064. */
  1065. LOCAL STATUS sh7615EndRecv
  1066.     (
  1067.     DRV_CTRL *  pDrvCtrl, /* device structure */
  1068.     SH7615_RD * pRxD  /* packet to process */
  1069.     )
  1070.     {
  1071.     END_OBJ *   pEndObj = &pDrvCtrl->end;
  1072.     M_BLK_ID  pMblk;
  1073.     CL_BLK_ID pClBlk;
  1074.     char*       pNewCluster;
  1075.     int         len;
  1076.     /* check for errors */
  1077.     if (pRxD->rDesc0 & RD0_RFE)
  1078.         {
  1079.         DRV_LOG (DRV_DEBUG_RX, "Receive with error RD0 = 0x%08x n", 
  1080.  pRxD->rDesc0, 2, 3, 4, 5, 6);
  1081.         END_ERR_ADD (pEndObj, MIB2_IN_ERRS, +1);
  1082.         goto cleanRxD;
  1083.         }
  1084.     DRV_LOG (DRV_DEBUG_RX, "Receive start n", 1, 2, 3, 4, 5, 6);
  1085.     /*
  1086.      * We implicitly are loaning here, if copying is necessary this
  1087.      * step may be skipped, but the data must be copied before being
  1088.      * passed up to the protocols.
  1089.      */
  1090.     
  1091.     pNewCluster = NET_BUF_ALLOC ();
  1092.     if (pNewCluster == NULL)
  1093.         {
  1094. pDrvCtrl->lastError.errCode = END_ERR_NO_BUF;
  1095. muxError (&pDrvCtrl->end, &pDrvCtrl->lastError);
  1096. DRV_LOG (DRV_DEBUG_RX, "Cannot loan!n", 1, 2, 3, 4, 5, 6);
  1097. END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
  1098. goto cleanRxD;
  1099.         }
  1100.     /* Grab a cluster block to marry to the cluster we received. */
  1101.     if ((pClBlk = netClBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT)) == NULL)
  1102.         {
  1103. pDrvCtrl->lastError.errCode = END_ERR_NO_BUF;
  1104. muxError (&pDrvCtrl->end, &pDrvCtrl->lastError);
  1105.         NET_BUF_FREE (pNewCluster);
  1106. DRV_LOG (DRV_DEBUG_RX, "Out of Cluster Blocks!n", 1, 2, 3, 4, 5, 6);
  1107. END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
  1108. goto cleanRxD;
  1109.         }
  1110.     
  1111.     /*
  1112.      * OK we've got a spare, let's get an M_BLK_ID and marry it to the
  1113.      * one in the ring.
  1114.      */
  1115.     if ((pMblk = mBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT, MT_DATA)) == NULL)
  1116.         {
  1117.         netClBlkFree (pDrvCtrl->end.pNetPool, pClBlk); 
  1118.         NET_BUF_FREE (pNewCluster);
  1119. DRV_LOG (DRV_DEBUG_RX, "Out of M Blocks!n", 1, 2, 3, 4, 5, 6);
  1120. END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
  1121. goto cleanRxD;
  1122.         }
  1123.     END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);
  1124.     len = SH7615END_FRAME_LEN_GET (pRxD->rDesc1); 
  1125.     /*
  1126.      * Invalidate cache and copy to ensure 4 byte alignment of IP header.
  1127.      * This is required by the IP network stack.
  1128.      */ 
  1129.     SH7615END_CACHE_INVALIDATE ((char *) (pRxD->rDesc2), len);
  1130.     len = (len + 1) & 0xfffffffe;
  1131.     bcopy((char*)pRxD->rDesc2,(char*)pRxD->rDesc2+2,len);
  1132.     /* Join the cluster to the MBlock */
  1133.     netClBlkJoin (pClBlk, (char *) (pRxD->rDesc3), SH7615END_BUFSIZ, NULL, 
  1134.   0, 0, 0);
  1135.     netMblkClJoin (pMblk, pClBlk);
  1136.     pMblk->mBlkHdr.mFlags |= M_PKTHDR;
  1137.     pMblk->mBlkHdr.mLen = len;
  1138.     pMblk->mBlkHdr.mData = (char *) (pRxD->rDesc2 + 2);
  1139.     pMblk->mBlkPktHdr.len  = pMblk->mBlkHdr.mLen;
  1140.     /* save the new True data buffer address for freeing later */
  1141.  
  1142.     pRxD->rDesc3 = (UINT32) pNewCluster;
  1143.     /* Install new data buffer - force 16 byte alignment */
  1144.     pRxD->rDesc2 = NET_TO_SH7615END_BUF (pNewCluster);
  1145.     /* mark the descriptor ready to receive, preserve the RDL bit */
  1146.  
  1147.     pRxD->rDesc0 = (pRxD->rDesc0 & RD0_RDL) | RD0_OWN;
  1148.  
  1149.     /* advance management index */
  1150.  
  1151.     pDrvCtrl->rxIndex = (pDrvCtrl->rxIndex + 1) % pDrvCtrl->numRds;
  1152.  
  1153.     /* Call the upper layer's receive routine. */
  1154.     DRV_LOG (DRV_DEBUG_RX, "Calling upper layer!n", 1, 2, 3, 4, 5, 6);
  1155.     END_RCV_RTN_CALL(&pDrvCtrl->end, pMblk);
  1156.     return (OK);
  1157. cleanRxD:
  1158.     /* mark the descriptor ready to receive - make sure to preserve the RDL bit */
  1159.     pRxD->rDesc0 = (pRxD->rDesc0 & RD0_RDL) | RD0_OWN;
  1160.  
  1161.     /* advance management index */
  1162.  
  1163.     pDrvCtrl->rxIndex = (pDrvCtrl->rxIndex + 1) % pDrvCtrl->numRds;
  1164.     return (OK);
  1165.     }
  1166. /*******************************************************************************
  1167. *
  1168. * sh7615EndRcvIntHandle - task level interrupt service for input packets
  1169. *
  1170. * This routine is called at task level indirectly by the interrupt
  1171. * service routine to do any message received processing.
  1172. *
  1173. * RETURNS: N/A.
  1174. */
  1175. LOCAL void sh7615EndRcvIntHandle
  1176.     (
  1177.     DRV_CTRL *pDrvCtrl /* interrupting device */
  1178.     )
  1179.     {
  1180.     SH7615_RD *pRxD;
  1181.     pDrvCtrl->rxHandling = TRUE; /* interlock with sh7615EndInt() */
  1182.     while ((pRxD = sh7615EndRxDGet (pDrvCtrl)) != NULL)
  1183. sh7615EndRecv (pDrvCtrl, pRxD);
  1184.     pDrvCtrl->rxHandling = FALSE; /* interlock with sh7615EndInt() */
  1185.     /* Make sure the Receive Request is still ON */
  1186.     SH7615END_REG_WRITE(E_DMAC_EDRRR, EDRRR_RR);
  1187.     /* enable receive interrupt */
  1188.     SH7615END_BIT_SET (E_DMAC_EESIPR, EESIPR_FRIP);
  1189.     }
  1190. /*******************************************************************************
  1191. *
  1192. * sh7615EndSend - transmit an ethernet packet
  1193. *
  1194. * This routine takes a M_BLK_ID sends off the data in the M_BLK_ID.
  1195. * The buffer must already have the addressing information properly installed
  1196. * in it.  This is done by a higher layer.  The last arguments are a free
  1197. * routine to be called when the device is done with the buffer and a pointer
  1198. * to the argument to pass to the free routine.
  1199. *
  1200. * RETURNS: OK on success; and ERROR otherwise.
  1201. */
  1202.  
  1203. LOCAL STATUS sh7615EndSend
  1204.     (
  1205.     DRV_CTRL * pDrvCtrl,
  1206.     M_BLK * pMblk
  1207.     )
  1208.     {
  1209.     SH7615_TD * pTxD;
  1210.     char *      pBuf;
  1211.     int         len;
  1212.     DRV_LOG (DRV_DEBUG_TX, "EndSendn", 1, 2, 3, 4, 5, 6);
  1213.     /* Gain exclusive access to transmit */
  1214.     END_TX_SEM_TAKE (&pDrvCtrl->end, WAIT_FOREVER);
  1215.  
  1216.     /* Get the next TXD */
  1217.     pTxD = sh7615EndTxDGet (pDrvCtrl);
  1218.     if (pTxD == NULL)
  1219.         {
  1220.         DRV_LOG (DRV_DEBUG_TX, "No available TxD-s n", 1, 2, 3, 4, 5, 6);
  1221.         END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_ERRS, +1);
  1222.         END_TX_SEM_GIVE (&pDrvCtrl->end);
  1223.  
  1224.         if (!pDrvCtrl->txCleaning && !pDrvCtrl->txBlocked)
  1225.             sh7615EndTxRingClean (pDrvCtrl);
  1226.  
  1227.         pDrvCtrl->txBlocked = TRUE;        /* transmitter not ready */
  1228.  
  1229.         return (END_ERR_BLOCK); /* just return without freeing mBlk chain */
  1230.         }
  1231.  
  1232.     pBuf = NET_BUF_ALLOC();
  1233.     if (pBuf == NULL)
  1234.         {
  1235. pDrvCtrl->lastError.errCode = END_ERR_NO_BUF;
  1236. muxError (&pDrvCtrl->end, &pDrvCtrl->lastError);
  1237.         DRV_LOG (DRV_DEBUG_TX, "No available TxBufs n", 1, 2, 3, 4, 5, 6);
  1238.         END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_ERRS, +1);
  1239.         END_TX_SEM_GIVE (&pDrvCtrl->end);
  1240.  
  1241.         if (!pDrvCtrl->txCleaning && !pDrvCtrl->txBlocked)
  1242.             sh7615EndTxRingClean (pDrvCtrl);
  1243.  
  1244.         pDrvCtrl->txBlocked = TRUE;        /* transmitter not ready */
  1245.         return (END_ERR_BLOCK); /* just return without freeing mBlk chain */
  1246.         }
  1247.     /*
  1248.      * Store the buf info. Do this before adjusting alignment below 
  1249.      * so that the netBufFree will work correctly later.
  1250.      */
  1251.  
  1252.     pDrvCtrl->freeBuf[pDrvCtrl->txIndex].pClBuf = pBuf;
  1253.  
  1254.     /* force 16 byte alignment of send buffer */
  1255.     (UINT32) pBuf = NET_TO_SH7615END_BUF (pBuf);
  1256.  
  1257.     /* Now copy data to 16 byte aligned location in pBuf and free Mblk */
  1258.     len = netMblkToBufCopy (pMblk, pBuf, NULL);
  1259.     len = max (ETHERSMALL, len);
  1260.     netMblkClChainFree (pMblk);
  1261.     /* flush the cache, if necessary */
  1262.  
  1263.     SH7615END_CACHE_FLUSH (pBuf, len);
  1264.     /* initialize the transmit descriptor -- preserve TD0_TDL bit */
  1265.     pTxD->tDesc0  = ((pTxD->tDesc0 & TD0_TDL) | (TD0_OWN | TD0_TFP));
  1266.     pTxD->tDesc1 = SH7615END_TBS_PUT(len);
  1267.     pTxD->tDesc2 = (UINT32) pBuf;
  1268.     pTxD->tDesc3 = 0;
  1269.     /* Advance our management index */
  1270.     pDrvCtrl->txIndex = (pDrvCtrl->txIndex + 1) % pDrvCtrl->numTds;
  1271.     SH7615END_REG_WRITE(E_DMAC_EDTRR, EDTRR_TR);  /* Transmit request */
  1272.     END_TX_SEM_GIVE (&pDrvCtrl->end);
  1273.  
  1274.     /* update statistics */
  1275.     END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_UCAST, +1);
  1276.  
  1277.     return (OK);
  1278.     }
  1279. /*******************************************************************************
  1280. *
  1281. * sh7615EndPollStart - starting polling mode
  1282. *
  1283. * This routine starts polling mode by disabling ethernet interrupts and
  1284. * setting the polling flag in the END_CTRL stucture.
  1285. *
  1286. * RETURNS: OK, always.
  1287. */
  1288.  
  1289. LOCAL STATUS sh7615EndPollStart
  1290.     (
  1291.     DRV_CTRL *  pDrvCtrl
  1292.     )
  1293.     {
  1294.     int         intLevel;
  1295.  
  1296.     DRV_LOG (DRV_DEBUG_POLL, "PollStartn", 1, 2, 3, 4, 5, 6);
  1297.  
  1298.     intLevel = intLock();
  1299.  
  1300.     /* Disable system interrupts */
  1301.     SYS_INT_DISABLE (pDrvCtrl);
  1302.  
  1303.     /* mask interrupts */
  1304.     SH7615END_BIT_CLR(E_DMAC_EESIPR, pDrvCtrl->intrMask);
  1305.  
  1306.     DRV_FLAGS_SET (SH7615END_POLLING);
  1307.  
  1308.     intUnlock (intLevel);
  1309.  
  1310.     return (OK);
  1311.     }
  1312. /*******************************************************************************
  1313. *
  1314. * sh7615EndPollStop - stop polling mode
  1315. *
  1316. * This function terminates polled mode operation.  The device returns to
  1317. * interrupt mode.
  1318. *
  1319. * The device interrupts are enabled, the current mode flag is switched
  1320. * to indicate interrupt mode and the device is then reconfigured for
  1321. * interrupt operation.
  1322. *
  1323. * RETURNS: OK, always.
  1324. */
  1325.  
  1326. LOCAL STATUS sh7615EndPollStop
  1327.     (
  1328.     DRV_CTRL *  pDrvCtrl
  1329.     )
  1330.     {
  1331.     int intLevel;
  1332.     DRV_LOG (DRV_DEBUG_POLL, "PollStopn", 1, 2, 3, 4, 5, 6);
  1333.     intLevel = intLock();
  1334.  
  1335.     DRV_FLAGS_CLR (SH7615END_POLLING);
  1336.     /* Enable chip interrupts */
  1337.     SH7615END_REG_WRITE(E_DMAC_EESIPR, pDrvCtrl->intrMask);
  1338.  
  1339.     /* Enable system interrupts */
  1340.     SYS_INT_ENABLE (pDrvCtrl);
  1341.     intUnlock (intLevel);
  1342.  
  1343.     DRV_LOG (DRV_DEBUG_POLL, "sn", 1, 2, 3, 4, 5, 6);
  1344.  
  1345.     return (OK);
  1346.     }
  1347. /*******************************************************************************
  1348. *
  1349. * sh7615EndPollSend - send a packet in polled mode
  1350. *
  1351. * This routine is called by a user to try and send a packet on the
  1352. * device.
  1353. *
  1354. * RETURNS: OK on success, EAGAIN on failure
  1355. */
  1356.  
  1357. LOCAL STATUS sh7615EndPollSend
  1358.     (
  1359.     DRV_CTRL * pDrvCtrl,
  1360.     M_BLK * pMblk
  1361.     )
  1362.     {
  1363.     SH7615_TD * pTxD;
  1364.     char * pBuf;
  1365.     char * pBufAligned;
  1366.     int len;
  1367.  
  1368.     DRV_LOG (DRV_DEBUG_POLL, "PollSendn", 1, 2, 3, 4, 5, 6);
  1369.     pTxD = sh7615EndTxDGet (pDrvCtrl);
  1370.     pBuf = NET_BUF_ALLOC ();
  1371.  
  1372.     if ((pTxD == NULL) || (pBuf == NULL))
  1373.         {
  1374. pDrvCtrl->lastError.errCode = END_ERR_NO_BUF;
  1375. muxError (&pDrvCtrl->end, &pDrvCtrl->lastError);
  1376.         sh7615EndTxRingClean (pDrvCtrl);
  1377.         if (pBuf)  NET_BUF_FREE (pBuf);
  1378.         return (EAGAIN);
  1379.         }
  1380.     /* force 16 byte alignment of send buffer */
  1381.  
  1382.     (UINT32) pBufAligned = NET_TO_SH7615END_BUF (pBuf);
  1383.  
  1384.     /* copy the MBLK */
  1385.     len = netMblkToBufCopy (pMblk, pBufAligned, NULL);
  1386.     len = max (ETHERSMALL, len);
  1387.     /* flush the cache, if necessary */
  1388.  
  1389.     SH7615END_CACHE_FLUSH (pBufAligned, len);
  1390.  
  1391.     pTxD->tDesc0 = ((pTxD->tDesc0 & TD0_TDL) | (TD0_OWN | TD0_TFP));
  1392.     pTxD->tDesc1 = SH7615END_TBS_PUT(len);
  1393.     pTxD->tDesc2 = (UINT32) pBufAligned;
  1394.     pTxD->tDesc3 = 0;
  1395.  
  1396.     /* Advance our management index */
  1397.     pDrvCtrl->txIndex = (pDrvCtrl->txIndex + 1) % pDrvCtrl->numTds;
  1398.  
  1399.     /* Transmit request */
  1400.     SH7615END_REG_WRITE(E_DMAC_EDTRR, EDTRR_TR);  
  1401.     /* The buffer does not belong to us; Spin until it can be freed */
  1402.     while (pTxD->tDesc0 & TD0_OWN)
  1403.         ;
  1404.     NET_BUF_FREE (pBuf);
  1405.  
  1406.     /* Try again on transmit errors */
  1407.     if (pTxD->tDesc0 & TD0_TFE)
  1408.         return (EAGAIN);
  1409.     return (EAGAIN);
  1410.     }
  1411. /*******************************************************************************
  1412. *
  1413. * sh7615EndPollReceive - get a packet in polled mode
  1414. *
  1415. * This routine is called by a user to try and get a packet from the
  1416. * device.
  1417. *
  1418. * RETURNS: OK on success, EAGAIN on failure.
  1419. */
  1420.  
  1421. LOCAL STATUS sh7615EndPollReceive
  1422.     (
  1423.     DRV_CTRL    *pDrvCtrl,
  1424.     M_BLK       *pMblk
  1425.     )
  1426.     {
  1427.     SH7615_RD  *pRxD;
  1428.     char        *pRxBuf;
  1429.     int         len;
  1430.     BOOL        gotOne=FALSE;
  1431.  
  1432.     DRV_LOG (DRV_DEBUG_POLL, "PollReceiven", 1, 2, 3, 4, 5, 6);
  1433.     if ((pMblk->mBlkHdr.mFlags & M_EXT) != M_EXT)
  1434.         return (EAGAIN);
  1435.     while (((pRxD = sh7615EndRxDGet (pDrvCtrl)) != NULL) && !gotOne)
  1436.         {
  1437.         /* Check if the packet was received OK */
  1438.         if (pRxD->rDesc0 & RD0_RFE)
  1439.             {
  1440.             /* Update the error statistics and discard the packet */
  1441.             END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
  1442.             }
  1443.         else
  1444.             {
  1445.             len = SH7615END_FRAME_LEN_GET (pRxD->rDesc1);
  1446.             if ((len <= pMblk->mBlkHdr.mLen) && (len >= ETHERSMALL))
  1447.                 {
  1448.                 gotOne = TRUE;
  1449.                 END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);
  1450.  
  1451.                 pMblk->mBlkHdr.mFlags |= M_PKTHDR; /* set the packet header */
  1452.                 pMblk->mBlkHdr.mLen = len;         /* set the data len */
  1453.                 pMblk->mBlkPktHdr.len = len;       /* set the total len */
  1454.  
  1455. /* cache invalidate to prepare for the copy */
  1456.                 pRxBuf = (char *) pRxD->rDesc2;
  1457.                 SH7615END_CACHE_INVALIDATE (pRxBuf, len);
  1458.                 /* bump the buffer mData by 2 to ensure alignment */
  1459.                 pMblk->mBlkHdr.mData +=2;
  1460.                 bcopy (pRxBuf, (char *)pMblk->mBlkHdr.mData, len);
  1461.                 }
  1462.             }
  1463.         /* mark the descriptor ready to receive - preserve the RDL bit */
  1464.  
  1465.         pRxD->rDesc0 = (pRxD->rDesc0 & RD0_RDL) | RD0_OWN;
  1466.  
  1467.         pDrvCtrl->rxIndex = (pDrvCtrl->rxIndex + 1) % pDrvCtrl->numRds;
  1468.         }
  1469.     return (gotOne ? OK : EAGAIN);
  1470.     }
  1471. /*******************************************************************************
  1472. *
  1473. * sh7615EndIoctl - the driver I/O control routine
  1474. *
  1475. * Process an ioctl request.
  1476. *
  1477. * This routine implements the network interface control functions.
  1478. * It handles EIOCSADDR, EIOCGADDR, EIOCSFLAGS, EIOCGFLAGS, EIOCMULTIADD,
  1479. * EIOCMULTIDEL, EIOCMULTIGET, EIOCPOLLSTART, EIOCPOLLSTOP, EIOCGMIB2 commands.
  1480. *
  1481. * RETURNS: A command specific response, usually OK or ERROR.
  1482. */
  1483. LOCAL STATUS sh7615EndIoctl
  1484.     (
  1485.     DRV_CTRL * pDrvCtrl, /* device receiving command */
  1486.     int cmd, /* ioctl command code */
  1487.     caddr_t  data /* command argument */
  1488.     )
  1489.     {
  1490.     int  error = 0;
  1491.     long  value;
  1492.     int         savedFlags;
  1493.     END_OBJ *   pEndObj=&pDrvCtrl->end;
  1494.     DRV_LOG (DRV_DEBUG_IOCTL, "Ioctl unit=0x%x cmd=%d data=0x%xn",
  1495.      pDrvCtrl->unit, cmd, (int)data, 4, 5, 6);
  1496.     switch (cmd)
  1497.         {
  1498.         case EIOCSADDR:
  1499.     if (data == NULL)
  1500. return (EINVAL);
  1501.             bcopy ((char *)data, (char *)END_HADDR(pEndObj),
  1502.    END_HADDR_LEN(pEndObj));
  1503.             break;
  1504.         case EIOCGADDR:
  1505.     if (data == NULL)
  1506. return (EINVAL);
  1507.             bcopy ((char *)END_HADDR(pEndObj), (char *)data,
  1508.     END_HADDR_LEN(pEndObj));
  1509.             break;
  1510.         case EIOCSFLAGS:
  1511.     value = (long)data;
  1512.     if (value < 0)
  1513. {
  1514. value = -value;
  1515.                 value--;
  1516. END_FLAGS_CLR (pEndObj, value);
  1517. }
  1518.     else
  1519. {
  1520. END_FLAGS_SET (pEndObj, value);
  1521. }
  1522.             /* handle IIF_PROMISC and IFF_ALLMULTI */
  1523.  
  1524.             savedFlags = DRV_FLAGS_GET();
  1525.             if (END_FLAGS_ISSET (pEndObj, IFF_PROMISC))
  1526.                 DRV_FLAGS_SET (SH7615END_PROMISC);
  1527.             else
  1528.                 DRV_FLAGS_CLR (SH7615END_PROMISC);
  1529.  
  1530.             if (END_FLAGS_GET(pEndObj) & (IFF_MULTICAST | IFF_ALLMULTI))
  1531.                 DRV_FLAGS_SET (SH7615END_MCAST);
  1532.             else
  1533.                 DRV_FLAGS_CLR (SH7615END_MCAST);
  1534.  
  1535.             DRV_LOG (DRV_DEBUG_IOCTL,
  1536.                        "EIOCSFLAGS!! endFlags=0x%x savedFlags=0x%x newFlags=0x%xn",
  1537.                         END_FLAGS_GET(pEndObj), savedFlags, DRV_FLAGS_GET(), 4, 5, 6);
  1538.  
  1539.             if ((DRV_FLAGS_GET() != savedFlags) &&
  1540.                 (END_FLAGS_GET(pEndObj) & IFF_UP))
  1541.                 sh7615EndModeSet (pDrvCtrl);
  1542.             break;
  1543.         case EIOCGFLAGS:
  1544.             DRV_LOG (DRV_DEBUG_IOCTL, "EIOCGFLAGS IOCTL: 0x%x: 0x%xn",
  1545.                     pEndObj->flags, *(long *)data, 0, 0, 0, 0);
  1546.  
  1547.             if (data == NULL)
  1548.                 error = EINVAL;
  1549.             else
  1550.                 *(long *)data = END_FLAGS_GET(pEndObj);
  1551.  
  1552.             break;
  1553.         case EIOCMULTIADD:
  1554.             DRV_LOG (DRV_DEBUG_IOCTL, "IOCTL EIOCMULTIADDn", 1, 2, 3, 4, 5, 6);
  1555.             error = sh7615EndMCastAddrAdd (pDrvCtrl, (char *)data);
  1556.             break;
  1557.  
  1558.         case EIOCMULTIDEL:
  1559.             DRV_LOG (DRV_DEBUG_IOCTL, "IOCTL EIOCMULTIDELn", 1, 2, 3, 4, 5, 6);
  1560.             error = sh7615EndMCastAddrDel (pDrvCtrl, (char *)data);
  1561.             break;
  1562.  
  1563.         case EIOCMULTIGET:
  1564.             DRV_LOG (DRV_DEBUG_IOCTL, "IOCTL EIOCMULTIGETn", 1, 2, 3, 4, 5, 6);
  1565.             error = sh7615EndMCastAddrGet (pDrvCtrl, (MULTI_TABLE *)data);
  1566.             break;
  1567.         case EIOCPOLLSTART:
  1568.             DRV_LOG (DRV_DEBUG_IOCTL, "IOCTL EIOCPOLLSTARTn", 1, 2, 3, 4, 5, 6);
  1569.             sh7615EndPollStart (pDrvCtrl);
  1570.             break;
  1571.  
  1572.         case EIOCPOLLSTOP:
  1573.             DRV_LOG (DRV_DEBUG_IOCTL, "IOCTL EIOCPOLLSTOPn", 1, 2, 3, 4, 5, 6);
  1574.             sh7615EndPollStop (pDrvCtrl);
  1575.             break;
  1576.         case EIOCGMIB2:
  1577.             if (data == NULL)
  1578.                 error=EINVAL;
  1579.             else
  1580.                 bcopy((char *)&pEndObj->mib2Tbl, (char *)data,
  1581.                       sizeof(pEndObj->mib2Tbl));
  1582.             DRV_LOG (DRV_DEBUG_IOCTL, "IOCTL EIOCGMIB2n", 1, 2, 3, 4, 5, 6);
  1583.             break;
  1584.  
  1585.         default:
  1586.             error = EINVAL;
  1587.         }
  1588.     return (error);
  1589.     }
  1590. /*******************************************************************************
  1591. *
  1592. * sh7615EndModeSet - promiscuous & multicast operation 
  1593. *
  1594. * This routine enables promiscuous and duplex mode if corresponding flags 
  1595. * are set.
  1596. *
  1597. * RETURNS: N/A
  1598. */
  1599.  
  1600. LOCAL void sh7615EndModeSet
  1601.     (
  1602.     DRV_CTRL    *pDrvCtrl
  1603.     )
  1604.     {
  1605.     /* NOTE - manual says mode should not be changed while
  1606.        Rx/Tx is enabled. To modify mode settings, first issue
  1607.        software reset */
  1608.     /* Set promiscuous mode if necessary */
  1609.     if (DRV_FLAGS_ISSET (SH7615END_PROMISC))
  1610. SH7615END_BIT_SET (ETHERC_ECMR, ECMR_PRM);
  1611.     /* Set duplex mode if necessary */
  1612.     if (DRV_FLAGS_ISSET (SH7615END_FD))
  1613. SH7615END_BIT_SET(ETHERC_ECMR, ECMR_DM);
  1614.     }
  1615.  
  1616. /******************************************************************************
  1617. *
  1618. * sh7615EndConfig - reconfigure the interface under us.
  1619. *
  1620. * Reconfigure the interface setting promiscuous mode, and changing the
  1621. * multicast interface list.
  1622. *
  1623. * RETURNS: N/A.
  1624. */
  1625. LOCAL void sh7615EndConfig
  1626.     (
  1627.     DRV_CTRL *pDrvCtrl /* device to be re-configured */
  1628.     )
  1629.     {
  1630.     UCHAR* pEnetAddr = pDrvCtrl->enetAddr;
  1631.     UINT32 MACAddr = 0;
  1632.     DRV_LOG (DRV_DEBUG_LOAD, "Configuring shendn", 0, 0, 0, 0, 0, 0);
  1633.     /* initialize the dp83843 Physical interface device */
  1634. #ifdef INCLUDE_PHY
  1635.     /* Check full duplex mode */
  1636.     DRV_FLAGS_CLR (SH7615END_FD);
  1637.     if (dp83843RegRead(PHYSTS) & 0x0004)
  1638. {
  1639. DRV_FLAGS_SET (SH7615END_FD);
  1640. }
  1641. #define PFC_PACR ((volatile UINT16 *)0xfffffc80)
  1642.     *PFC_PACR = *PFC_PACR | (UINT16) 0x0004; /* LINKSTA pin */
  1643. #endif
  1644.     /* set depth of FIFO */
  1645.     SH7615END_REG_WRITE(E_DMAC_FDR, ((pDrvCtrl->userFlags & 0x70) << 4) |
  1646.      (pDrvCtrl->userFlags & 0x7));
  1647.     /* Write start of receive and transmit rings */
  1648.     SH7615END_REG_WRITE(E_DMAC_RDLAR, (UINT32)pDrvCtrl->rxRing);
  1649.     SH7615END_REG_WRITE(E_DMAC_TDLAR, (UINT32)pDrvCtrl->txRing);
  1650.     /* set MAC Address */
  1651.     MACAddr  = (UINT32)pEnetAddr[0] << 24;
  1652.     MACAddr |= (UINT32)pEnetAddr[1] << 16;
  1653.     MACAddr |= (UINT32)pEnetAddr[2] << 8;
  1654.     MACAddr |= (UINT32)pEnetAddr[3];
  1655.     SH7615END_REG_WRITE(ETHERC_MAHR, MACAddr);
  1656.     MACAddr  = (UINT32)pEnetAddr[4] << 8;
  1657.     MACAddr |= (UINT32)pEnetAddr[5];
  1658.     SH7615END_REG_WRITE(ETHERC_MALR, MACAddr);
  1659.     /* set receive frame length register - specifies max receiveable length */
  1660.     SH7615END_REG_WRITE(ETHERC_RFLR, 0x5F0); /* 1520 bytes */
  1661.  
  1662.     /* clear any pending interrupts */
  1663.     SH7615END_REG_WRITE(ETHERC_ECSR, ECSR_CLEAR);
  1664.     SH7615END_REG_WRITE(E_DMAC_EESR, EESR_CLEAR);
  1665.  
  1666.     /* set operating mode and start the receiver */
  1667.     sh7615EndModeSet (pDrvCtrl);
  1668.     /* start the transmitter, receiver */
  1669.     SH7615END_REG_WRITE(E_DMAC_RCR, RCR_RNC); /* continuous mode */ 
  1670.     SH7615END_REG_WRITE(E_DMAC_EDRRR, EDRRR_RR); /* Receive request */
  1671.     SH7615END_BIT_SET(ETHERC_ECMR, ECMR_TE);
  1672.     SH7615END_BIT_SET(ETHERC_ECMR, ECMR_RE);
  1673.     /* set up the interrupt mask */
  1674.     pDrvCtrl->intrMask = EESIPR_FRIP | EESIPR_TCIP | EESIPR_ECIIP;
  1675.     /* enable interrupts at the device */
  1676.     SH7615END_REG_WRITE(E_DMAC_EESIPR, pDrvCtrl->intrMask);
  1677.     SH7615END_REG_WRITE(ETHERC_ECSIPR, ECSIPR_LCHNGIP);
  1678.     return;
  1679.     }
  1680. /*******************************************************************************
  1681. *
  1682. * sh7615EndMCastAddrAdd - add a multicast address
  1683. *
  1684. * This routine adds a multicast address to whatever the driver
  1685. * is already listening for.
  1686. *
  1687. * RETURNS: OK on success, ERROR otherwise.
  1688. */
  1689.  
  1690. LOCAL STATUS sh7615EndMCastAddrAdd
  1691.     (
  1692.     DRV_CTRL *  pDrvCtrl,
  1693.     char *      pAddr
  1694.     )
  1695.     {
  1696.     int retVal;
  1697.  
  1698.     DRV_LOG (DRV_DEBUG_IOCTL, "MCastAddrAddn", 0, 0, 0, 0, 0, 0);
  1699.  
  1700.     retVal = etherMultiAdd (&pDrvCtrl->end.multiList, pAddr);
  1701.  
  1702.     if (retVal == ENETRESET)
  1703.         sh7615EndConfig (pDrvCtrl);
  1704.  
  1705.     return (OK);
  1706.     }
  1707. /*******************************************************************************
  1708. *
  1709. * sh7615EndMCastAddrDel - remove a multicast address
  1710. *
  1711. * This routine deletes a multicast address from the current list of
  1712. * multicast addresses.
  1713. *
  1714. * RETURNS: OK on success, ERROR otherwise.
  1715. */
  1716.  
  1717. LOCAL STATUS sh7615EndMCastAddrDel
  1718.     (
  1719.     DRV_CTRL *  pDrvCtrl,
  1720.     char *      pAddr
  1721.     )
  1722.     {
  1723.     int retVal;
  1724.  
  1725.     DRV_LOG (DRV_DEBUG_IOCTL, "MCastAddrDeln", 0, 0, 0, 0, 0, 0);
  1726.  
  1727.     retVal = etherMultiDel (&pDrvCtrl->end.multiList, pAddr);
  1728.  
  1729.     if (retVal == ENETRESET)
  1730.         sh7615EndConfig (pDrvCtrl);
  1731.  
  1732.     return (OK);
  1733.     }
  1734. /*******************************************************************************
  1735. *
  1736. * sh7615EndMCastAddrGet - retreive current multicast address list
  1737. *
  1738. * This routine returns the current multicast address list in <pTable>
  1739. *
  1740. * RETURNS: OK on success; otherwise ERROR.
  1741. */
  1742.  
  1743. LOCAL STATUS sh7615EndMCastAddrGet
  1744.     (
  1745.     DRV_CTRL *  pDrvCtrl,
  1746.     MULTI_TABLE *pTable
  1747.     )
  1748.     {
  1749.     DRV_LOG (DRV_DEBUG_IOCTL, "MCastAddrGetn", 0, 0, 0, 0, 0, 0);
  1750.  
  1751.     return (etherMultiGet (&pDrvCtrl->end.multiList, pTable));
  1752.     }
  1753. /*******************************************************************************
  1754. *
  1755. * sh7615EnetAddrGet - get the Ethernet address.
  1756. *
  1757. * This routine gets the ethernet address by calling the appropriate
  1758. * BSP routine.
  1759. *
  1760. * RETURNS: N/A.
  1761. */
  1762.  
  1763. LOCAL void sh7615EnetAddrGet
  1764.     (
  1765.     DRV_CTRL *  pDrvCtrl,
  1766.     char * addr
  1767.     )
  1768.     {
  1769.     int i;
  1770.     char bytes[6];
  1771.   
  1772.     SYS_ENET_ADDR_GET (pDrvCtrl, bytes);
  1773.  
  1774.     /* For big endian we need to swap byte order */
  1775.     for (i=0; i<6; i++)
  1776. *addr++ = bytes[5-i];
  1777.     }
  1778. /*******************************************************************************
  1779. *
  1780. * sh7615EndReset - reset device
  1781. *
  1782. * This routines issues a software reset of the SH7615 on-chip EDMAC.
  1783. *
  1784. * RETURNS: N/A.
  1785. */
  1786. LOCAL void sh7615EndReset
  1787.     (
  1788.     DRV_CTRL *pDrvCtrl
  1789.     )
  1790.     {
  1791.     /*
  1792.      * Note - this also sets Tx/Rx descriptor length to 16 bytes, which is
  1793.      * what we want.
  1794.      *
  1795.      * This should reset all internal registers to the initial values.
  1796.      * Both the etherC AND the E-DMAC regs are reset.
  1797.      * Consequently, all interrupts should be masked.
  1798.      */
  1799.     SH7615END_REG_WRITE (E_DMAC_EDMR, EDMR_SWR);
  1800.     }
  1801. #ifdef DRV_DEBUG
  1802. /*******************************************************************************
  1803. *
  1804. * sh7615EndRegDump - reads all ETHERC and EDMAC registers and print the value
  1805. *
  1806. * This routine reads all the registers of the SH7615 on-chip ETHERC and EDMAC.
  1807. * Only for debug purpose.
  1808. *
  1809. * RETURNS: N/A.
  1810. *
  1811. * NOMANUAL
  1812. */
  1813. void sh7615EndRegDump()
  1814.     {
  1815.     UINT32 value;
  1816.     SH7615END_REG_READ(E_DMAC_EDMR, value);
  1817.     logMsg ("E_DMAC_EDMR:   0x%xn", value, 0, 0, 0, 0, 0);
  1818.     SH7615END_REG_READ(E_DMAC_EDTRR, value);
  1819.     logMsg ("E_DMAC_EDTRR:  0x%xn", value, 0, 0, 0, 0, 0);
  1820.     SH7615END_REG_READ(E_DMAC_EDRRR, value);
  1821.     logMsg ("E_DMAC_EDRRR:  0x%xn", value, 0, 0, 0, 0, 0);
  1822.     SH7615END_REG_READ(E_DMAC_TDLAR, value);
  1823.     logMsg ("E_DMAC_TDLAR:  0x%xn", value, 0, 0, 0, 0, 0);
  1824.     SH7615END_REG_READ(E_DMAC_RDLAR, value);
  1825.     logMsg ("E_DMAC_RDLAR:  0x%xn", value, 0, 0, 0, 0, 0);
  1826.     SH7615END_REG_READ(E_DMAC_EESR, value);
  1827.     logMsg ("E_DMAC_EESR:   0x%xn", value, 0, 0, 0, 0, 0);
  1828.     SH7615END_REG_READ(E_DMAC_EESIPR, value);
  1829.     logMsg ("E_DMAC_EESIPR: 0x%xn", value, 0, 0, 0, 0, 0);
  1830.     SH7615END_REG_READ(E_DMAC_TRSCER, value);
  1831.     logMsg ("E_DMAC_TRSCER: 0x%xn", value, 0, 0, 0, 0, 0);
  1832.     SH7615END_REG_READ(E_DMAC_RMFCR, value);
  1833.     logMsg ("E_DMAC_RMFCR:  0x%xn", value, 0, 0, 0, 0, 0);
  1834.     SH7615END_REG_READ(E_DMAC_TFTR, value);
  1835.     logMsg ("E_DMAC_TFTR:   0x%xn", value, 0, 0, 0, 0, 0);
  1836.     SH7615END_REG_READ(E_DMAC_FDR, value);
  1837.     logMsg ("E_DMAC_FDR:    0x%xn", value, 0, 0, 0, 0, 0);
  1838.     SH7615END_REG_READ(E_DMAC_RCR, value);
  1839.     logMsg ("E_DMAC_RCR:    0x%xn", value, 0, 0, 0, 0, 0);
  1840.     SH7615END_REG_READ(E_DMAC_EDOCR, value);
  1841.     logMsg ("E_DMAC_EDOCR:  0x%xn", value, 0, 0, 0, 0, 0);
  1842.     SH7615END_REG_READ(ETHERC_ECMR, value);
  1843.     logMsg ("ETHERC_ECMR:   0x%xn", value, 0, 0, 0, 0, 0);
  1844.     SH7615END_REG_READ(ETHERC_ECSR, value);
  1845.     logMsg ("ETHERC_ECSR:   0x%xn", value, 0, 0, 0, 0, 0);
  1846.     SH7615END_REG_READ(ETHERC_ECSIPR, value);
  1847.     logMsg ("ETHERC_ECSIPR: 0x%xn", value, 0, 0, 0, 0, 0);
  1848.     SH7615END_REG_READ(ETHERC_PIR, value);
  1849.     logMsg ("ETHERC_PIR:    0x%xn", value, 0, 0, 0, 0, 0);
  1850.     SH7615END_REG_READ(ETHERC_MAHR, value);
  1851.     logMsg ("ETHERC_MAHR:   0x%xn", value, 0, 0, 0, 0, 0);
  1852.     SH7615END_REG_READ(ETHERC_MALR, value);
  1853.     logMsg ("ETHERC_MALR:   0x%xn", value, 0, 0, 0, 0, 0);
  1854.     SH7615END_REG_READ(ETHERC_RFLR, value);
  1855.     logMsg ("ETHERC_RFLR:   0x%xn", value, 0, 0, 0, 0, 0);
  1856.     SH7615END_REG_READ(ETHERC_PSR, value);
  1857.     logMsg ("ETHERC_PSR:    0x%xn", value, 0, 0, 0, 0, 0);
  1858.     SH7615END_REG_READ(ETHERC_TROCR, value);
  1859.     logMsg ("ETHERC_TROCR:  0x%xn", value, 0, 0, 0, 0, 0);
  1860.     SH7615END_REG_READ(ETHERC_CDCR, value);
  1861.     logMsg ("ETHERC_CDCR:   0x%xn", value, 0, 0, 0, 0, 0);
  1862.     SH7615END_REG_READ(ETHERC_LCCR, value);
  1863.     logMsg ("ETHERC_LCCR:   0x%xn", value, 0, 0, 0, 0, 0);
  1864.     SH7615END_REG_READ(ETHERC_CNDCR, value);
  1865.     logMsg ("ETHERC_CNDCR:  0x%xn", value, 0, 0, 0, 0, 0);
  1866.     SH7615END_REG_READ(ETHERC_IFLCR, value);
  1867.     logMsg ("ETHERC_IFLCR:  0x%xn", value, 0, 0, 0, 0, 0);
  1868.     SH7615END_REG_READ(ETHERC_CEFCR, value);
  1869.     logMsg ("ETHERC_CEFCR:  0x%xn", value, 0, 0, 0, 0, 0);
  1870.     SH7615END_REG_READ(ETHERC_FRECR, value);
  1871.     logMsg ("ETHERC_FRECR:  0x%xn", value, 0, 0, 0, 0, 0);
  1872.     SH7615END_REG_READ(ETHERC_TSFRCR, value);
  1873.     logMsg ("ETHERC_TSFRCR: 0x%xn", value, 0, 0, 0, 0, 0);
  1874.     SH7615END_REG_READ(ETHERC_TLFRCR, value);
  1875.     logMsg ("ETHERC_TLFRCR: 0x%xn", value, 0, 0, 0, 0, 0);
  1876.     SH7615END_REG_READ(ETHERC_RFCR, value);
  1877.     logMsg ("ETHERC_RFCR:   0x%xn", value, 0, 0, 0, 0, 0);
  1878.     SH7615END_REG_READ(ETHERC_MAFCR, value);
  1879.     logMsg ("ETHERC_MAFCR:  0x%xn", value, 0, 0, 0, 0, 0);
  1880.     }
  1881. #endif  /* DRV_DEBUG */
  1882. #ifdef INCLUDE_PHY
  1883. /*******************************************************************************
  1884. *
  1885. * dp83843SingleBitRead - reads a single bit value from the dp83843
  1886. *
  1887. * This routine reads a single bit value from the dp83843 via the etherc's PHY
  1888. * Interface Register (PIR). 
  1889. *
  1890. * RETURNS: N/A.
  1891. */
  1892. LOCAL UINT16 dp83843SingleBitRead (void)
  1893.     {
  1894.     UINT32 data;
  1895.     /* lead clock and data direction is read */
  1896.     SH7615END_REG_WRITE (ETHERC_PIR, ~PIR_MMD & PIR_MDC);         
  1897.     /* read data */
  1898.     SH7615END_REG_READ (ETHERC_PIR, data);
  1899.     /* 
  1900.      * NOTE - I assume this should be a write for the trailing clock,
  1901.      * but the doc is confusing, saying "MII control register read"
  1902.      */
  1903.     SH7615END_REG_WRITE (ETHERC_PIR, 0x0);         
  1904.     /* shift data */
  1905.     if (data & PIR_MDI)
  1906.         return 1;
  1907.     else 
  1908.         return 0;
  1909.     }
  1910. /*******************************************************************************
  1911. *
  1912. * dp83843SingleBitWrite - writes a single bit value to the dp83843
  1913. *
  1914. * This routine writes a single bit value to the dp83843 via the etherc's PHY
  1915. * Interface Register (PIR). The dp83843 is programmed one bit at a time.
  1916. *
  1917. * RETURNS: N/A.
  1918. */
  1919. LOCAL void dp83843SingleBitWrite 
  1920.     (
  1921.     int bitVal
  1922.     )
  1923.     {
  1924.     UINT32 data;
  1925.     UINT32 leadClock;
  1926.     UINT32 trailClock;
  1927.     if (bitVal)
  1928.         data = PIR_MDO | PIR_MMD;
  1929.     else
  1930.         data = PIR_MMD;
  1931.     leadClock  = data | PIR_MDC;
  1932.     trailClock = data; 
  1933.     /* Set data and write direction */
  1934.     SH7615END_REG_WRITE (ETHERC_PIR, (PIR_MMD & ~PIR_MDC) | (bitVal << 2) ); 
  1935.     /* Provide the clock leading and trailing pulses to latch on */
  1936.     SH7615END_REG_WRITE (ETHERC_PIR,  PIR_MMD | PIR_MDC | (bitVal << 2) );   
  1937.     SH7615END_REG_WRITE (ETHERC_PIR,  (PIR_MMD & ~PIR_MDC) | (bitVal << 2)); 
  1938.     }
  1939. /*******************************************************************************
  1940. *
  1941. * dp83843GetPackt - compose a frame format for the PHY
  1942. *
  1943. * This routine composes a frame format for the PHY chip according to
  1944. * the following scheme:
  1945. *   <idle><ST><OP><AAAAA><RRRRR><TA>
  1946. * where:
  1947. * ST: start command (01)
  1948. * OP: operation code (01: write, 10: read)
  1949. * AAAAA: address of the PHY chip.
  1950. * RRRRR: register of the PHY chip.
  1951. * TA: turnaround (10: write, Z0: read)
  1952. *
  1953. * Example write sequence to ANAR (address offset == 0x4)
  1954. *
  1955. *      5       0       9       2      this routine returns: 0x5092
  1956. *    _____   _____   _____   _____  
  1957. *   |     | |     | |     | |     |
  1958. *   0 1 0 1 0 0 0 0 1 0 0 1 0 0 1 0
  1959. *   | | | | |       | |       | | |
  1960. *    -   -   -------   -------   -
  1961. *    s   o    phy       reg      T
  1962. *    t   p   addr      addr      A
  1963. *    a        1         0x4
  1964. *    r   w
  1965. *    t   r
  1966. *
  1967. * This routine returns a 16-bit pattern. Note: the <idle> at the
  1968. * beginning is not included. For reading, the TA field is irrelevant.
  1969. *
  1970. * RETURNS: the frame packet.
  1971. */
  1972. LOCAL UINT16 dp83843GetPackt
  1973.     (
  1974.     UCHAR phyAddr, /* Address of the PHY in the transaction */
  1975.     UCHAR phyReg, /* Register interested in the transaction */
  1976.     BOOL writePck /* frame for writing if true */
  1977.     )
  1978.     {
  1979.     UINT16 value = 0;
  1980.     /* start command */
  1981.     value |= ((0x0001 & 0x0003) << 14); 
  1982.     
  1983.     /* Operation command */
  1984.     if( writePck )
  1985. value |= ((0x0001 & 0x0003) << 12); /* write command */
  1986.     else
  1987. value |= ((0x0002 & 0x0003) << 12); /* read command */
  1988.     /* Address of the PHY chip */
  1989.     value |= ((phyAddr & 0x001f) << 7);
  1990.     /* Register */
  1991.     value |= ((phyReg & 0x001f) << 2);
  1992.     /* turnaround */
  1993.     if( writePck )
  1994. value |= 0x0002; /* write operation only */
  1995.     else
  1996. value |= 0x0000;
  1997.     return value;
  1998.     }
  1999. #if 0    /* Not used currently */
  2000. /*******************************************************************************
  2001. *
  2002. * dp83843RegWrite - writes a dp83843 register
  2003. *
  2004. * This routine writes a UINT16 value to a dp83843 register via the etherc's PHY
  2005. * Interface Register (PIR). dp83843 registers are all 16bit.
  2006. *
  2007. * RETURNS: N/A.
  2008. *
  2009. * NOMANUAL
  2010. */
  2011.  
  2012. LOCAL void dp83843RegWrite
  2013.     (
  2014.     UINT16 regAddr,
  2015.     UINT16 regData 
  2016.     )
  2017.     {
  2018.     int i;
  2019.     UINT16 pckFrame;
  2020.     pckFrame = dp83843GetPackt(PHY_ADDR, regAddr, TRUE);
  2021.     
  2022.     /* this preamble step may not be necessary - BMSR's bit 6 has default
  2023.        value of 1 which means the device is supposed to be able to operate
  2024.        without the preamble. However, it does still need 32 bits after a
  2025.        reset.
  2026.      */
  2027.     for(i=0; i<32; i++)
  2028.         dp83843SingleBitWrite(1);    /* preamble is 32 1's */
  2029.     for(i=0; i<16; i++)              /* start, opcode, devAddrr, regAddr and turn */
  2030.         {
  2031.         if((pckFrame & 0x8000)==0x8000)
  2032.             dp83843SingleBitWrite(1);
  2033.         else
  2034.             dp83843SingleBitWrite(0);
  2035.  
  2036.         pckFrame = pckFrame << 1;
  2037.         }
  2038.     for(i=0; i<16; i++)              /* regdata */
  2039.         {
  2040.         if((regData & 0x8000)==0x8000)
  2041.     {
  2042.             dp83843SingleBitWrite(1);
  2043.     }
  2044.         else
  2045.     {
  2046.             dp83843SingleBitWrite(0);
  2047.     }
  2048.  
  2049.         regData = regData << 1;
  2050.         }
  2051.     /* independent bus release */
  2052.     SH7615END_REG_WRITE (ETHERC_PIR,  ~PIR_MDC & ~PIR_MMD );     
  2053.     
  2054.     }
  2055. #endif
  2056. /*******************************************************************************
  2057. *
  2058. * dp83843RegRead - reads a dp83843 register
  2059. *
  2060. * This routine reads a UINT16 register from a dp83843 via the etherc's PHY
  2061. * Interface Register (PIR). dp83843 registers are all 16bit.
  2062. *
  2063. * RETURNS: value read.
  2064. */
  2065. LOCAL UINT16 dp83843RegRead
  2066.     (
  2067.     UINT16 regAddr /* register to be read */
  2068.     )
  2069.     {
  2070.     int i;
  2071.     UINT16 value = 0;
  2072.     UINT16 data;
  2073.     UINT16 pckFrame;
  2074.     pckFrame = dp83843GetPackt(PHY_ADDR, regAddr, FALSE);
  2075.     /* 
  2076.      * NOTE: this preamble step may not be necessary - BMSR's bit 6 has 
  2077.      * default value of 1 which means the device is supposed to be able to
  2078.      * operate without the preamble. However, it does still need 32 bits 
  2079.      * after a reset.
  2080.      */
  2081.     for(i = 0; i < 32; i++)
  2082.         {
  2083.         dp83843SingleBitWrite(1);    /* preamble is 32 1's */
  2084. }
  2085.     
  2086.      /* 
  2087.       * NOTE - ought to hard code in the start, opcode and devAddr here and
  2088.       * only pass in the regAddr offset as defined in the doc. This would
  2089.       * make the macro defs in sh7615End.h more understandable. Then, they
  2090.       * would just be the simple offsets as opposed to containing the start
  2091.       * opcode and devAddr also.
  2092.       */
  2093.     /* write the start, opcode, devAddr and regAddr. Note - this is only 14 bits */
  2094.     for(i = 0; i < 14; i++)            
  2095.         {
  2096.         if( (pckFrame & 0x8000) == 0x8000 )
  2097.             {
  2098.             dp83843SingleBitWrite(1);
  2099.             }
  2100.         else
  2101.             {
  2102.             dp83843SingleBitWrite(0);
  2103.             }
  2104.  
  2105.         pckFrame = pckFrame << 1;
  2106.         }
  2107.     /* release the bus */
  2108.     SH7615END_REG_WRITE (ETHERC_PIR, 0);
  2109.     SH7615END_REG_WRITE (ETHERC_PIR, PIR_MDC);
  2110.     SH7615END_REG_WRITE (ETHERC_PIR, 0);
  2111.     /* read bit 0 of TA */
  2112.     
  2113.     if( dp83843SingleBitRead() == 1 )
  2114. DRV_LOG(DRV_DEBUG_PHY,"dp83843RegRead: Last bit of TA fild is Set!n",
  2115.   1,2,3,4,5,6);
  2116.     /* read data */
  2117.     for(i = 15; i >= 0; i--) 
  2118.         {
  2119.         data = dp83843SingleBitRead();
  2120.         value |= (data << i);
  2121.         }
  2122.     return value;
  2123.     }
  2124. #ifdef DRV_DEBUG
  2125. /*******************************************************************************
  2126. *
  2127. * dp83843RegDump - reads all the dp83843 registers and print the value
  2128. *
  2129. * This routine reads all the registers of a dp83843 via the etherc's PHY
  2130. * Interface Register (PIR) and prints the values. Only for debug purpose.
  2131. *
  2132. * RETURNS: N/A.
  2133. *
  2134. * NOMANUAL
  2135. */
  2136. void dp83843RegDump (void)
  2137.     {
  2138.     DRV_LOG(DRV_DEBUG_PHY,"nn PHY CHIP Registers:nn",1,2,3,4,5,6)
  2139.     DRV_LOG(DRV_DEBUG_PHY,"BMCR:tt%04xn",
  2140.       dp83843RegRead(BMCR),2,3,4,5,6);
  2141.     DRV_LOG(DRV_DEBUG_PHY,"BMSR:tt%04xn",
  2142.       dp83843RegRead(BMSR),2,3,4,5,6);
  2143.     DRV_LOG(DRV_DEBUG_PHY,"PHYIDR1:tt%04xn",
  2144.       dp83843RegRead(PHYIDR1),2,3,4,5,6);
  2145.     DRV_LOG(DRV_DEBUG_PHY,"PHYIDR2:tt%04xn",
  2146.       dp83843RegRead(PHYIDR2),2,3,4,5,6);
  2147.     DRV_LOG(DRV_DEBUG_PHY,"ANAR:tt%04xn",
  2148.       dp83843RegRead(ANAR),2,3,4,5,6);
  2149.     DRV_LOG(DRV_DEBUG_PHY,"ANLPAR:tt%04xn",
  2150.       dp83843RegRead(ANLPAR),2,3,4,5,6);
  2151.     DRV_LOG(DRV_DEBUG_PHY,"ANER:tt%04xn",
  2152.       dp83843RegRead(ANER),2,3,4,5,6);
  2153.     DRV_LOG(DRV_DEBUG_PHY,"ANNPTR:tt%04xn",
  2154.       dp83843RegRead(ANNPTR),2,3,4,5,6);
  2155.     DRV_LOG(DRV_DEBUG_PHY,"PHYSTS:tt%04xn",
  2156.       dp83843RegRead(PHYSTS),2,3,4,5,6);
  2157.     DRV_LOG(DRV_DEBUG_PHY,"MIPSCR:tt%04xn",
  2158.       dp83843RegRead(MIPSCR),2,3,4,5,6);
  2159.     DRV_LOG(DRV_DEBUG_PHY,"MIPGSR:tt%04xn",
  2160.       dp83843RegRead(MIPGSR),2,3,4,5,6);
  2161.     DRV_LOG(DRV_DEBUG_PHY,"DCR:tt%04xn",
  2162.       dp83843RegRead(DCR),2,3,4,5,6);
  2163.     DRV_LOG(DRV_DEBUG_PHY,"FCSCR:tt%04xn",
  2164.       dp83843RegRead(FCSCR),2,3,4,5,6);
  2165.     DRV_LOG(DRV_DEBUG_PHY,"RECR:tt%04xn",
  2166.       dp83843RegRead(RECR),2,3,4,5,6);
  2167.     DRV_LOG(DRV_DEBUG_PHY,"PCSR:tt%04xn",
  2168.       dp83843RegRead(PCSR),2,3,4,5,6);
  2169.     DRV_LOG(DRV_DEBUG_PHY,"LBR:tt%04xn",
  2170.       dp83843RegRead(LBR),2,3,4,5,6);
  2171.     DRV_LOG(DRV_DEBUG_PHY,"BTSCR:tt%04xn",
  2172.       dp83843RegRead(BTSCR),2,3,4,5,6);
  2173.     DRV_LOG(DRV_DEBUG_PHY,"PHYCTL:tt%04xn",
  2174.       dp83843RegRead(PHYCTRL),2,3,4,5,6);
  2175.     }
  2176. #endif /* DRV_DEBUG */
  2177. #endif /* INCLUDE_PHY */