ksz8851snl.c

Go to the documentation of this file.
00001 /**************************************************************************/
00015 #include <stdio.h>
00016 
00017 #include "ksz8851snl.h"
00018 #include "ksz8851snl_spi.h"
00019 #include "em_assert.h"
00020 
00021 #include "lwip/sys.h"
00022 #include "lwipopts.h"
00023 #include "debug.h"
00024 
00025 #ifndef LWIP4EFM32
00026 #error "lwiopts.h for EFM32 are not included"
00027 #endif
00028 
00029 /* Register definitions */
00030 #define MARL      0x10 
00031 #define MARM      0x12 
00032 #define MARH      0x14 
00033 #define OBCR      0x20 
00034 #define GRR       0x26 
00035 #define TXCR      0x70 
00036 #define RXCR1     0x74 
00037 #define RXCR2     0x76 
00038 #define TXMIR     0x78 
00039 #define RXFHSR    0x7C 
00040 #define RXFHBCR   0x7E 
00041 #define TXQCR     0x80 
00042 #define RXQCR     0x82 
00043 #define TXFDPR    0x84 
00044 #define RXFDPR    0x86 
00045 #define IER       0x90 
00046 #define ISR       0x92 
00047 #define RXFCTR    0x9C 
00048 #define TXNTFSR   0x9E 
00049 #define FCLWR     0xB0 
00050 #define FCHWR     0xB2 
00051 #define CIDER     0xC0 
00052 #define IACR      0xC8 
00053 #define IADLR     0xD0 
00054 #define IADHR     0xD2 
00055 #define PMECR     0xD4 
00056 #define PHYRR     0xD8 
00057 #define P1MBCR    0xE4 
00058 #define P1CR      0xF6 
00059 #define P1SR      0xF8 
00061 #define KSZ8851SNL_CHIP_ID           0x8870 
00062 #define CHIP_ID_MASK                 0xFFF0 
00063 #define ONE_FRAME_THRES              0x0001 
00064 #define FD_PTR_AUTO_INC              0x4000 
00065 #define CLEAR_INT                    0xFFFF 
00066 #define NO_INT                       0x0000 
00067 #define TX_MEM_AVAIL_MASK            0x1FFF 
00068 #define FRAME_ID_MASK                0x003F 
00069 #define CHECKSUM_VALID_FRAME_MASK    0x3C17 
00073 #define VALID_FRAME_MASK             0x8000 
00076 #define RX_BYTE_CNT_MASK             0x0FFF 
00077 #define LSB_MASK                     0x00FF 
00078 #define MSB_POS                      0x0008 
00079 #define TX_INT_on_COMPLETION         0x8000 
00080 #define WORD_SIZE                    0x0004 
00081 #define EXTRA_SIZE                   0x0008 
00082 #define BLOCKING_RECEIVE             0      
00083 #define WATERMARK_6KB                0x0600 
00084 #define WATERMARK_4KB                0x0400 
00085 /* Silicon Laboratories MAC address space */
00086 #define HIGH_QMU_MAC_H               0x00   
00087 #define HIGH_QMU_MAC_L               0x0B   
00088 #define MID_QMU_MAC_H                0x57   
00089 #define BYTE_MASK                    0x00FF 
00090 #define BYTE_SIZE                    0x0008 
00092 /* TX Flow Control Register Options */
00093 
00095 #define   TX_FLOW_CTRL_ICMP_CHECKSUM    0x0100
00096 
00097 #define   TX_FLOW_CTRL_TCP_CHECKSUM     0x0040
00098 
00099 #define   TX_FLOW_CTRL_IP_CHECKSUM      0x0020
00100 
00101 #define   TX_FLOW_CTRL_FLUSH_QUEUE      0x0010
00102 
00103 #define   TX_FLOW_CTRL_FLOW_ENABLE      0x0008
00104 
00105 #define   TX_FLOW_CTRL_PAD_ENABLE       0x0004
00106 
00107 #define   TX_FLOW_CTRL_CRC_ENABLE       0x0002
00108 
00109 #define   TX_FLOW_CTRL_ENABLE           0x0001
00110 
00112 #define   TX_FLOW_CTRL_CONFIG           (TX_FLOW_CTRL_ICMP_CHECKSUM | \
00113                                          TX_FLOW_CTRL_TCP_CHECKSUM |  \
00114                                          TX_FLOW_CTRL_IP_CHECKSUM |   \
00115                                          TX_FLOW_CTRL_FLOW_ENABLE |   \
00116                                          TX_FLOW_CTRL_PAD_ENABLE |    \
00117                                          TX_FLOW_CTRL_CRC_ENABLE)
00118 
00119 /* TXQ Command Register Options */
00121 #define   TXQ_AUTO_ENQUEUE         0x0004
00122 
00123 #define   TXQ_MEM_AVAILABLE_INT    0x0002
00124 
00125 #define   TXQ_ENQUEUE              0x0001
00126 
00127 
00128 /* RX Flow Control Register 1 Options */
00130 #define   RX_FLOW_CTRL_FLUSH_QUEUE       0x8000
00131 
00132 #define   RX_FLOW_CTRL_UDP_CHECKSUM      0x4000
00133 
00134 #define   RX_FLOW_CTRL_TCP_CHECKSUM      0x2000
00135 
00136 #define   RX_FLOW_CTRL_IP_CHECKSUM       0x1000
00137 
00138 #define   RX_FLOW_CTRL_MAC_FILTER        0x0800
00139 
00140 #define   RX_FLOW_CTRL_FLOW_ENENABLE     0x0400
00141 
00142 #define   RX_FLOW_CTRL_BAD_PACKET        0x0200
00143 
00144 #define   RX_FLOW_CTRL_BROADCAST_ENABLE  0x0080
00145 
00146 #define   RX_FLOW_CTRL_MULTICAST_ENABLE  0x0040
00147 
00148 #define   RX_FLOW_CTRL_UNICAST_ENABLE    0x0020
00149 
00150 #define   RX_FLOW_CTRL_PROMISCUOUS_MODE  0x0012
00151 
00152 #define   RX_FLOW_CTRL_RX_ALL            0x0010
00153 
00154 #define   RX_FLOW_CTRL_INVERSE_FILTER    0x0002
00155 
00156 #define   RX_FLOW_CTRL_RX_ENABLE         0x0001
00157 
00159 #define   RX_FLOW_CTRL1_CONFIG           (RX_FLOW_CTRL_UDP_CHECKSUM     |  \
00160                                           RX_FLOW_CTRL_TCP_CHECKSUM     |  \
00161                                           RX_FLOW_CTRL_IP_CHECKSUM      |  \
00162                                           RX_FLOW_CTRL_MAC_FILTER       |  \
00163                                           RX_FLOW_CTRL_FLOW_ENENABLE    |  \
00164                                           RX_FLOW_CTRL_BROADCAST_ENABLE |  \
00165                                           RX_FLOW_CTRL_UNICAST_ENABLE)
00166 
00167 /* RX Flow Control Register 2 Options */
00168 /* SPI Receive Data Burst Length */
00170 #define   RX_FLOW_CTRL_BURST_LEN_MASK        0x00E0
00171 
00172 #define   RX_FLOW_CTRL_BURST_LEN_4           0x0000
00173 
00174 #define   RX_FLOW_CTRL_BURST_LEN_8           0x0020
00175 
00176 #define   RX_FLOW_CTRL_BURST_LEN_16          0x0040
00177 
00178 #define   RX_FLOW_CTRL_BURST_LEN_32          0x0060
00179 
00180 #define   RX_FLOW_CTRL_BURST_LEN_FRAME       0x0080
00181 
00182 #define   RX_FLOW_CTRL_IPV6_UDP_FRAG_PASS    0x0010
00183 
00184 #define   RX_FLOW_CTRL_IPV6_UDP_ZERO_PASS    0x0008
00185 
00186 #define   RX_FLOW_CTRL_UDP_LITE_CHECKSUM     0x0004
00187 
00188 #define   RX_FLOW_CTRL_ICMP_CHECKSUM         0x0002
00189 
00190 #define   RX_FLOW_CTRL_BLOCK_MAC             0x0001
00191 
00193 #define   RX_FLOW_CTRL2_CONFIG               (RX_FLOW_CTRL_IPV6_UDP_FRAG_PASS | \
00194                                               RX_FLOW_CTRL_UDP_LITE_CHECKSUM |  \
00195                                               RX_FLOW_CTRL_ICMP_CHECKSUM |      \
00196                                               RX_FLOW_CTRL_BURST_LEN_FRAME)
00197 
00198 /* RXQ Command Register Options */
00200 #define   RXQ_ON_TIME_INT            0x1000
00201 
00202 #define   RXQ_ON_BYTE_CNT_INT        0x0800
00203 
00204 #define   RXQ_ON_FRAME_CNT_INT       0x0400
00205 
00206 #define   RXQ_TWOBYTE_OFFSET         0x0200
00207 
00208 #define   RXQ_EN_ON_TIME_INT         0x0080
00209 
00210 #define   RXQ_EN_ON_BYTE_CNT_INT     0x0040
00211 
00212 #define   RXQ_EN_ON_FRAME_CNT_INT    0x0020
00213 
00214 #define   RXQ_AUTO_DEQUEUE           0x0010
00215 
00216 #define   RXQ_START_DMA              0x0008
00217 
00218 #define   RXQ_RELEASE_ERROR_FRAME    0x0001
00219 
00221 #define   RXQ_CMD_CONFIG             (RXQ_EN_ON_FRAME_CNT_INT | \
00222                                       RXQ_AUTO_DEQUEUE)
00223 
00224 /* Port 1 Status Register */
00226 #define PORT1_AN_DONE                 0x0040
00227 
00228 #define PORT1_LINK_GOOD               0x0020
00229 
00230 /* Port 1 Control Register Options */
00232 #define   PORT1_LED_OFF               0x8000
00233 
00234 #define   PORT1_TX_DISABLE            0x4000
00235 
00236 #define   PORT1_AUTO_NEG_RESTART      0x2000
00237 
00238 #define   PORT1_POWER_DOWN            0x0800
00239 
00240 #define   PORT1_AUTO_MDIX_DISABLE     0x0400
00241 
00242 #define   PORT1_FORCE_MDIX            0x0200
00243 
00244 #define   PORT1_AUTO_NEG_ENABLE       0x0080
00245 
00246 #define   PORT1_FORCE_100_MBIT        0x0040
00247 
00248 #define   PORT1_FORCE_FULL_DUPLEX     0x0020
00249 
00250 #define   PORT1_AUTO_NEG_FLOW_CTRL    0x0010
00251 
00252 #define   PORT1_AUTO_NEG_100BTX_FD    0x0008
00253 
00254 #define   PORT1_AUTO_NEG_100BTX       0x0004
00255 
00256 #define   PORT1_AUTO_NEG_10BT_FD      0x0002
00257 
00258 #define   PORT1_AUTO_NEG_10BT         0x0001
00259 
00261 #define   PORT1_CONFIG          (PORT1_AUTO_NEG_ENABLE    | \
00262                                  PORT1_FORCE_100_MBIT     | \
00263                                  PORT1_FORCE_FULL_DUPLEX  | \
00264                                  PORT1_AUTO_NEG_FLOW_CTRL | \
00265                                  PORT1_AUTO_NEG_100BTX_FD | \
00266                                  PORT1_AUTO_NEG_100BTX    | \
00267                                  PORT1_AUTO_NEG_10BT_FD   | \
00268                                  PORT1_AUTO_NEG_10BT      )
00269 
00270 /* Global Reset Register Options */
00272 #define QMU_MODULE_SOFT_RESET    0x0002
00273 
00274 #define GLOBAL_SOFT_RESET        0x0001
00275 
00277 #define PHY_RESET                0x0001
00278 
00279 /* P1MBCR register */
00281 #define DIGITAL_LOOPBACK     0x4000
00282 
00283 #define FORCE_100            0x2000
00284 
00285 #define AUTO_NEG             0x1000
00286 
00287 #define RESTART_AUTO_NEG     0x0200
00288 
00289 #define FORCE_FULL_DUPLEX    0x0100
00290 
00292 #define TX_MEMORY_WAIT_MS    500
00293 
00295 #define FRAME_COUNT_THRESHOLD 1
00296 
00298 #define MIB_MASK                    0x1C00       
00299 #define MIB_RxByte                  0x00         
00300 #define MIB_XXX                     0x01         
00301 #define MIB_RxUndersizePkt          0x02         
00302 #define MIB_RxFragments             0x03         
00303 #define MIB_RxOversize              0x04         
00304 #define MIB_RxJabbers               0x05         
00305 #define MIB_RxSymbolError           0x06         
00306 #define MIB_RxCRCError              0x07         
00307 #define MIB_RxAlignmentError        0x08         
00308 #define MIB_RxControl8808Pkts       0x09         
00309 #define MIB_RxPausePkts             0x0A         
00310 #define MIB_RxBroadcast             0x0B         
00311 #define MIB_RxMulticast             0x0C         
00312 #define MIB_RxUnicast               0x0D         
00313 #define MIB_Rx64Octets              0x0E         
00314 #define MIB_Rx65to127Octets         0x0F         
00315 #define MIB_Rx128to255Octets        0x10         
00316 #define MIB_Rx256to511Octets        0x11         
00317 #define MIB_Rx512to1023Octets       0x12         
00318 #define MIB_Rx1024to1521Octets      0x13         
00319 #define MIB_Rx1522to2000Octets      0x14         
00320 #define MIB_TxByte                  0x15         
00321 #define MIB_TxLateCollision         0x16         
00322 #define MIB_TxPausePkts             0x17         
00323 #define MIB_TxBroadcastPkts         0x18         
00324 #define MIB_TxMulticastPkts         0x19         
00325 #define MIB_TxUnicastPkts           0x1A         
00326 #define MIB_TxDeferred              0x1B         
00327 #define MIB_TxTotalCollision        0x1C         
00328 #define MIB_TxExcessiveCollision    0x1D         
00329 #define MIB_TxSingleCollision       0x1E         
00330 #define MIB_TxMultipleCollision     0x1F         
00333 #define READ_UNSAFE_REGISTERS       0
00334 
00335 static uint16_t frameId = 0;        
00336 static uint8_t  macAddress[6];      
00337 static uint16_t rxFrameCount;
00338 static uint32_t interruptCnt = 0;
00350 static KSZ8851SLN_mib_t mibCounters;
00351 
00352 /***************************************************************************/
00362 static uint32_t MIBCountersRead(uint16_t offset)
00363 {
00364   uint16_t data;
00365   uint32_t counter;
00366 
00367   data = MIB_MASK | offset;
00368   KSZ8851SNL_SPI_WriteRegister(IACR, data);
00369   counter  = KSZ8851SNL_SPI_ReadRegister(IADLR);
00370   counter |= KSZ8851SNL_SPI_ReadRegister(IADHR) << 16;
00371 
00372   return counter;
00373 }
00374 
00375 /***************************************************************************/
00382 void KSZ8851SNL_MIBCountersUpdate(void)
00383 {
00384   mibCounters.RxByteCnt           += MIBCountersRead(MIB_RxByte);
00385   mibCounters.RxUndersizePktCnt   += MIBCountersRead(MIB_RxUndersizePkt);
00386   mibCounters.RxFragmentsCnt      += MIBCountersRead(MIB_RxFragments);
00387   mibCounters.RxOversizeCnt       += MIBCountersRead(MIB_RxOversize);
00388   mibCounters.RxJabbersCnt        += MIBCountersRead(MIB_RxJabbers);
00389   mibCounters.RxSymbolErrorCnt    += MIBCountersRead(MIB_RxSymbolError);
00390   mibCounters.RxCRCErrorCnt       += MIBCountersRead(MIB_RxCRCError);
00391   mibCounters.RxPausePktsCnt      += MIBCountersRead(MIB_RxPausePkts);
00392   mibCounters.RxBroadcastCnt      += MIBCountersRead(MIB_RxBroadcast);
00393   mibCounters.RxMulticastCnt      += MIBCountersRead(MIB_RxMulticast);
00394   mibCounters.RxUnicastCnt        += MIBCountersRead(MIB_RxUnicast);
00395   mibCounters.TxByteCnt           += MIBCountersRead(MIB_TxByte);
00396   mibCounters.TxPausePktsCnt      += MIBCountersRead(MIB_TxPausePkts);
00397   mibCounters.TxBroadcastPktsCnt  += MIBCountersRead(MIB_TxBroadcastPkts);
00398   mibCounters.TxMulticastPktsCnt  += MIBCountersRead(MIB_TxMulticastPkts);
00399   mibCounters.TxUnicastPktsCnt    += MIBCountersRead(MIB_TxUnicastPkts);
00400   mibCounters.TxDeferredCnt       += MIBCountersRead(MIB_TxDeferred);
00401   mibCounters.TxTotalCollisionCnt += MIBCountersRead(MIB_TxTotalCollision);
00402 }
00403 
00404 /***************************************************************************/
00409 void KSZ8851SNL_MIBCountersDump(void)
00410 {
00411   printf("####################### MIB COUNTER DUMP ########################\n");
00412   printf("MIB_RxByteCnt           = %lu\n", mibCounters.RxByteCnt);
00413   printf("MIB_RxUndersizePktCnt   = %lu\n", mibCounters.RxUndersizePktCnt);
00414   printf("MIB_RxFragmentsCnt      = %lu\n", mibCounters.RxFragmentsCnt);
00415   printf("MIB_RxOversizeCnt       = %lu\n", mibCounters.RxOversizeCnt);
00416   printf("MIB_RxJabbersCnt        = %lu\n", mibCounters.RxJabbersCnt);
00417   printf("MIB_RxSymbolErrorCnt    = %lu\n", mibCounters.RxSymbolErrorCnt);
00418   printf("MIB_RxCRCErrorCnt       = %lu\n", mibCounters.RxCRCErrorCnt);
00419   printf("MIB_RxPausePktsCnt      = %lu\n", mibCounters.RxPausePktsCnt);
00420   printf("MIB_RxBroadcastCnt      = %lu\n", mibCounters.RxBroadcastCnt);
00421   printf("MIB_RxMulticastCnt      = %lu\n", mibCounters.RxMulticastCnt);
00422   printf("MIB_RxUnicastCnt        = %lu\n", mibCounters.RxUnicastCnt);
00423   printf("MIB_TxByteCnt           = %lu\n", mibCounters.TxByteCnt);
00424   printf("MIB_TxPausePktsCnt      = %lu\n", mibCounters.TxPausePktsCnt);
00425   printf("MIB_TxBroadcastPktsCnt  = %lu\n", mibCounters.TxBroadcastPktsCnt);
00426   printf("MIB_TxMulticastPktsCnt  = %lu\n", mibCounters.TxMulticastPktsCnt);
00427   printf("MIB_TxUnicastPktsCnt    = %lu\n", mibCounters.TxUnicastPktsCnt);
00428   printf("MIB_TxDeferredCnt       = %lu\n", mibCounters.TxDeferredCnt);
00429   printf("MIB_TxTotalCollisionCnt = %lu\n", mibCounters.TxTotalCollisionCnt);
00430   printf("#################################################################\n");
00431 }
00432 
00433 /***************************************************************************/
00437 void KSZ8851SNL_AllRegistersDump(void)
00438 {
00439   printf("###################### ALL REGISTER DUMP ########################\n");
00440   int i;
00441   for (i = 0x00; i < 0xFF; i += 0x02)
00442   {
00443     if ((i % 8 == 0) && (i > 0))
00444     {
00445       printf("\n");
00446     }
00447     printf("REG[0x%02X]=0x%04X ", i, KSZ8851SNL_SPI_ReadRegister(i));
00448   }
00449   printf("\n");
00450   printf("#################################################################\n");
00451 }
00452 
00453 /***************************************************************************/
00457 void KSZ8851SNL_RegistersDump(void)
00458 {
00459   printf("##################### SPECIAL REGISTER DUMP ######################\n");
00460   printf("MARL  [0x%02X]=0x%04X\n", MARL,   KSZ8851SNL_SPI_ReadRegister(MARL));
00461   printf("MARM  [0x%02X]=0x%04X\n", MARM,   KSZ8851SNL_SPI_ReadRegister(MARM));
00462   printf("MARH  [0x%02X]=0x%04X\n", MARH,   KSZ8851SNL_SPI_ReadRegister(MARH));
00463   printf("OBCR  [0x%02X]=0x%04X\n", OBCR,   KSZ8851SNL_SPI_ReadRegister(OBCR));
00464   printf("GRR   [0x%02X]=0x%04X\n", GRR,    KSZ8851SNL_SPI_ReadRegister(GRR));
00465   printf("TXCR  [0x%02X]=0x%04X\n", TXCR,   KSZ8851SNL_SPI_ReadRegister(TXCR));
00466   printf("RXCR1 [0x%02X]=0x%04X\n", RXCR1,  KSZ8851SNL_SPI_ReadRegister(RXCR1));
00467   printf("RXCR2 [0x%02X]=0x%04X\n", RXCR2,  KSZ8851SNL_SPI_ReadRegister(RXCR2));
00468   printf("TXMIR [0x%02X]=0x%04X\n", TXMIR,  KSZ8851SNL_SPI_ReadRegister(TXMIR));
00469 #if (READ_UNSAFE_REGISTERS)
00470   printf("RXFHSR[0x%02X]=0x%04X\n", RXFHSR, KSZ8851SNL_SPI_ReadRegister(RXFHSR));
00471 #endif
00472   printf("TXQCR [0x%02X]=0x%04X\n", TXQCR,  KSZ8851SNL_SPI_ReadRegister(TXQCR));
00473   printf("RXQCR [0x%02X]=0x%04X\n", RXQCR,  KSZ8851SNL_SPI_ReadRegister(RXQCR));
00474   printf("TXFDPR[0x%02X]=0x%04X\n", TXFDPR, KSZ8851SNL_SPI_ReadRegister(TXFDPR));
00475   printf("RXFDPR[0x%02X]=0x%04X\n", RXFDPR, KSZ8851SNL_SPI_ReadRegister(RXFDPR));
00476   printf("IER   [0x%02X]=0x%04X\n", IER,    KSZ8851SNL_SPI_ReadRegister(IER));
00477   printf("ISR   [0x%02X]=0x%04X\n", ISR,    KSZ8851SNL_SPI_ReadRegister(ISR));
00478   printf("RXFCTR[0x%02X]=0x%04X\n", RXFCTR, KSZ8851SNL_SPI_ReadRegister(RXFCTR));
00479 #if (READ_UNSAFE_REGISTERS)
00480   printf("TXNTFSR[0x%02X]=0x%04X\n", TXNTFSR, KSZ8851SNL_SPI_ReadRegister(TXNTFSR));
00481 #endif
00482   printf("CIDER [0x%02X]=0x%04X\n", CIDER,  KSZ8851SNL_SPI_ReadRegister(CIDER));
00483   printf("PHYRR [0x%02X]=0x%04X\n", PHYRR,  KSZ8851SNL_SPI_ReadRegister(PHYRR));
00484   printf("P1MBCR[0x%02X]=0x%04X\n", P1MBCR, KSZ8851SNL_SPI_ReadRegister(P1MBCR));
00485   printf("P1CR  [0x%02X]=0x%04X\n", P1CR,   KSZ8851SNL_SPI_ReadRegister(P1CR));
00486   printf("#################################################################\n");
00487 }
00488 
00489 /**************************************************************************/
00492 void KSZ8851SNL_IntEnable(void)
00493 {
00494   if (interruptCnt)
00495   {
00496     interruptCnt--;
00497   }
00498   if (interruptCnt == 0)
00499   {
00500     /* Enable interrupts */
00501     KSZ8851SNL_SPI_WriteRegister(IER, KSZ8851SNL_INT_ENABLE_MASK);
00502   }
00503 }
00504 
00505 /**************************************************************************/
00508 void KSZ8851SNL_IntDisable(void)
00509 {
00510   KSZ8851SNL_SPI_WriteRegister(IER, NO_INT);
00511   interruptCnt++;
00512 }
00513 
00514 /**************************************************************************/
00521 void KSZ8851SNL_IntClear(uint16_t flags)
00522 {
00523   KSZ8851SNL_SPI_WriteRegister(ISR, flags);
00524 }
00525 
00526 /**************************************************************************/
00529 uint16_t KSZ8851SNL_IntGet(void)
00530 {
00531   return KSZ8851SNL_SPI_ReadRegister(ISR);
00532 }
00533 
00534 /**************************************************************************/
00541 void KSZ8851SNL_PMECRStatusClear(uint16_t flags)
00542 {
00543   uint16_t status = KSZ8851SNL_SPI_ReadRegister(PMECR) | flags;
00544   KSZ8851SNL_SPI_WriteRegister(PMECR, status);
00545 }
00546 
00547 /**************************************************************************/
00550 uint16_t KSZ8851SNL_RXQCRGet(void)
00551 {
00552   return KSZ8851SNL_SPI_ReadRegister(RXQCR);
00553 }
00554 
00555 /**************************************************************************/
00558 void KSZ8851SNL_FrameCounterSet(void)
00559 {
00560   /* Read the frame count and threshold register */
00561   uint16_t rxftr = KSZ8851SNL_SPI_ReadRegister(RXFCTR);
00562   /* Extract the actual number of frames from RX_FRAME_THRES_REG*/
00563   rxFrameCount = rxftr >> MSB_POS;
00564 }
00565 
00566 /**************************************************************************/
00569 void KSZ8851SNL_TxQueueReset(void)
00570 {
00571   uint16_t data;
00572 
00573   data = KSZ8851SNL_SPI_ReadRegister(TXCR);
00574   /* Disable TX */
00575   data &= ~TX_FLOW_CTRL_ENABLE;
00576   KSZ8851SNL_SPI_WriteRegister(TXCR, data);
00577   /* Flush */
00578   data |= TX_FLOW_CTRL_FLUSH_QUEUE;
00579   KSZ8851SNL_SPI_WriteRegister(TXCR, data);
00580   /* normal op - no flush */
00581   data &= ~TX_FLOW_CTRL_FLUSH_QUEUE;
00582   KSZ8851SNL_SPI_WriteRegister(TXCR, data);
00583   /* Enable TX */
00584   data |= TX_FLOW_CTRL_ENABLE;
00585   KSZ8851SNL_SPI_WriteRegister(TXCR, data);
00586 }
00587 
00588 /**************************************************************************/
00591 void KSZ8851SNL_RxQueueReset(void)
00592 {
00593   uint16_t data;
00594 
00595   data = KSZ8851SNL_SPI_ReadRegister(RXCR1);
00596   /* Disable RX */
00597   data &= ~RX_FLOW_CTRL_RX_ENABLE;
00598   KSZ8851SNL_SPI_WriteRegister(RXCR1, data);
00599   /* Flush */
00600   KSZ8851SNL_SPI_WriteRegister(RXCR1, data);
00601   /* Clear flush */
00602   data &= ~RX_FLOW_CTRL_FLUSH_QUEUE;
00603   KSZ8851SNL_SPI_WriteRegister(RXCR1, data);
00604   /* Write default config with enable set */
00605   data |= RX_FLOW_CTRL_RX_ENABLE;
00606   KSZ8851SNL_SPI_WriteRegister(RXCR1, data);
00607 }
00608 
00609 /**************************************************************************/
00612 uint16_t KSZ8851SNL_FrameCounterGet(void)
00613 {
00614   return rxFrameCount;
00615 }
00616 
00617 /***************************************************************************/
00620 void KSZ8851SNL_Init(void)
00621 {
00622   uint16_t data;
00623 
00624   /* Initialize SPI Interface */
00625   KSZ8851SNL_SPI_Init();
00626 
00627   /* Reset PHY module */
00628   KSZ8851SNL_SPI_WriteRegister(PHYRR, PHY_RESET);
00629 
00630   /* Reset Soft (clear registers of PHY, MAC, QMU, DMA) */
00631   data = KSZ8851SNL_SPI_ReadRegister(GRR);
00632   data &= ~GLOBAL_SOFT_RESET;
00633   KSZ8851SNL_SPI_WriteRegister(GRR, data);
00634 
00635   /* Reset Soft (clear registers of PHY, MAC, QMU, DMA) */
00636   data = KSZ8851SNL_SPI_ReadRegister(GRR);
00637   data &= ~GLOBAL_SOFT_RESET;
00638   KSZ8851SNL_SPI_WriteRegister(GRR, data);
00639 
00640   /* Read the chip ID and check if that is correct */
00641   data = KSZ8851SNL_SPI_ReadRegister(CIDER);
00642 
00643   /* The CIDER lower bits [3..1] are defined as revision number,
00644    *   thus a mask needs to be applied
00645    */
00646 
00647   /* this is a hard assert - abort  */
00648   EFM_ASSERT((data & CHIP_ID_MASK) == KSZ8851SNL_CHIP_ID);
00649 
00650   /* Write the Queue Management Unit MAC Address */
00651   KSZ8851SNL_MacAddressGet(macAddress);
00652   /* Write the MAC Address into the MAC registers */
00653   KSZ8851SNL_SPI_WriteRegister(MARH, (macAddress[0] << 8) | macAddress[1]);
00654   KSZ8851SNL_SPI_WriteRegister(MARM, (macAddress[2] << 8) | macAddress[3]);
00655   KSZ8851SNL_SPI_WriteRegister(MARL, (macAddress[4] << 8) | macAddress[5]);
00656 
00657   /* Enable QMU Transmit Frame Data Pointer Auto Increment */
00658   KSZ8851SNL_SPI_WriteRegister(TXFDPR, FD_PTR_AUTO_INC);
00659 
00660   /* Enable QMU Transmit:
00661    *  flow control,
00662    *  padding,
00663    *  CRC,
00664    *  checksum generation.
00665    */
00666   KSZ8851SNL_SPI_WriteRegister(TXCR, TX_FLOW_CTRL_CONFIG);
00667 
00668   /* Enable QMU Receive Frame Data Pointer Auto Increment */
00669   KSZ8851SNL_SPI_WriteRegister(RXFDPR, FD_PTR_AUTO_INC);
00670 
00671   /* Configure Receive Frame Threshold for one frame */
00672   KSZ8851SNL_SPI_WriteRegister(RXFCTR, FRAME_COUNT_THRESHOLD);
00673 
00674   /* Set RX queue low watermark to 10240 bytes for issuing of
00675      stop PAUSE frames (flow control) */
00676   data = 0xA00;
00677   KSZ8851SNL_SPI_WriteRegister(FCLWR, data);
00678 
00679   /* Enable QMU Receive:
00680    *  flow control,
00681    *  receive all broadcast frame,
00682    *  receive unicast frame,
00683    *  IP/TCP/UDP/ICMP checksum generation.
00684    */
00685   KSZ8851SNL_SPI_WriteRegister(RXCR1, RX_FLOW_CTRL1_CONFIG);
00686 
00687   /* Enable QMU Receive:
00688    *  ICMP/UDP Lite frame checksum verification,
00689    *  UDP Lite frame checksum generation,
00690    *  IPv6 UDP fragment frame pass.
00691    */
00692   KSZ8851SNL_SPI_WriteRegister(RXCR2, RX_FLOW_CTRL2_CONFIG);
00693 
00694   /* Enable QMU Receive:
00695    *  IP Header Two-Byte Offset,
00696    *  Receive Frame Count Threshold,
00697    *  RXQ Auto-Dequeue frame.
00698    */
00699   KSZ8851SNL_SPI_WriteRegister(RXQCR, RXQ_CMD_CONFIG);
00700 
00701   /* Restart Port 1 auto-negotiation */
00702   KSZ8851SNL_SPI_WriteRegister(P1CR, PORT1_CONFIG | PORT1_AUTO_NEG_RESTART);
00703 
00704   /* Clear interrupts */
00705   KSZ8851SNL_SPI_WriteRegister(ISR, CLEAR_INT);
00706 }
00707 
00708 
00709 /***************************************************************************/
00712 void KSZ8851SNL_Enable(void)
00713 {
00714   uint16_t data;
00715 
00716   KSZ8851SNL_SPI_WriteRegister(IER, KSZ8851SNL_INT_ENABLE_MASK);
00717 
00718   /* Enable QMU Transmit */
00719   data  = KSZ8851SNL_SPI_ReadRegister(TXCR);
00720   data |= TX_FLOW_CTRL_ENABLE;
00721   KSZ8851SNL_SPI_WriteRegister(TXCR, data);
00722 
00723   /* Enable QMU Receive */
00724   data  = KSZ8851SNL_SPI_ReadRegister(RXCR1);
00725   data |= RX_FLOW_CTRL_RX_ENABLE;
00726   KSZ8851SNL_SPI_WriteRegister(RXCR1, data);
00727 }
00728 
00729 
00730 /***************************************************************************/
00737 bool KSZ8851SNL_TransmitBegin(uint16_t length)
00738 {
00739   uint16_t txmir;
00740   uint16_t data, reqSize;
00741   uint8_t  outbuf[4];
00742 
00743   /* Wait for previous frame to finish before setting up a new one */
00744   while (KSZ8851SNL_SPI_ReadRegister(TXQCR) & TXQ_ENQUEUE)
00745   {
00746     ;
00747   }
00748 
00749   /* Make sure there is room for
00750    *
00751    * 4 bytes Control Word
00752    * 4 bytes Byte Count
00753    * n bytes Packet
00754    * 4 bytes CRC
00755    */
00756   reqSize = length + 12;
00757   txmir = KSZ8851SNL_SPI_ReadRegister(TXMIR) & TX_MEM_AVAIL_MASK;
00758   LWIP_DEBUGF(NETIF_DEBUG, ("KSZ8851SNL_LongTransmitInit: txmir =%hu  reqSize = %hu \n", txmir, reqSize));
00759 
00760   if (txmir < reqSize)
00761   {
00762     /* TXQ is out of memory */
00763     LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_LEVEL_WARNING, ("Not enough TXQ Memory, available=%u required=%u\n", txmir, reqSize));
00764     return false;
00765   }
00766 
00767   LWIP_DEBUGF(NETIF_DEBUG, ("KSZ8851SNL_LongTransmitInit: Memory available >  txmir =%hu  reqSize = %hu \n", txmir, reqSize));
00768   /* Enable TXQ write access */
00769   data = KSZ8851SNL_SPI_ReadRegister(RXQCR) | RXQ_START_DMA;
00770   KSZ8851SNL_SPI_WriteRegister(RXQCR, data);
00771 
00772   /* Write frame ID, control word and byte count */
00773   outbuf[0] = (frameId++ & FRAME_ID_MASK);
00774   outbuf[1] = 0x80; /*  TX_INT_on_COMPLETION */
00775   outbuf[2] = length & LSB_MASK;
00776   outbuf[3] = length >> MSB_POS;
00777 
00778   /* Start the SPI Transfer and send frame header */
00779   KSZ8851SNL_SPI_WriteFifoBegin();
00780   KSZ8851SNL_SPI_WriteFifo(4, outbuf);
00781 
00782   return true;
00783 }
00784 
00785 
00786 /***************************************************************************/
00801 void KSZ8851SNL_Transmit(uint16_t length, const uint8_t *buffer)
00802 {
00803   EFM_ASSERT(buffer != NULL);
00804   KSZ8851SNL_SPI_WriteFifo(length, buffer);
00805 }
00806 
00807 /***************************************************************************/
00819 void KSZ8851SNL_TransmitEnd(uint16_t length)
00820 {
00821   uint16_t data;
00822   uint16_t padding;
00823   uint8_t dummy[4] = {0x00};
00824 
00825   /* Padding packet to 4 byte boundary */
00826   if (length % 4)
00827   {
00828     padding = 4 - (length % 4);
00829     KSZ8851SNL_SPI_WriteFifo(padding, dummy);
00830   }
00831 
00832   /* Stop the SPI Transfer */
00833   KSZ8851SNL_SPI_WriteFifoEnd();
00834 
00835   /* Disable TXQ write access */
00836   data = KSZ8851SNL_SPI_ReadRegister(RXQCR) & (~RXQ_START_DMA);
00837   KSZ8851SNL_SPI_WriteRegister(RXQCR, data);
00838 
00839   /* Start TXQ Manual enqueue */
00840   data = KSZ8851SNL_SPI_ReadRegister(TXQCR) | TXQ_ENQUEUE;
00841   KSZ8851SNL_SPI_WriteRegister(TXQCR, data);
00842 }
00843 
00844 /***************************************************************************/
00848 static void ReleaseIncosistentFrame(void)
00849 {
00850   uint16_t data;
00851   /* Issue the Release error frame command */
00852   data = KSZ8851SNL_SPI_ReadRegister(RXQCR) | RXQ_RELEASE_ERROR_FRAME;
00853   KSZ8851SNL_SPI_WriteRegister(RXQCR, data);
00854 
00855   /* Wait for PHY to clear the command/flag */
00856   while (KSZ8851SNL_SPI_ReadRegister(RXQCR) & RXQ_RELEASE_ERROR_FRAME)
00857   {
00858     ;
00859   }
00860 }
00861 
00862 /***************************************************************************/
00875 uint16_t KSZ8851SNL_Receive(uint16_t length, uint8_t *buffer)
00876 {
00877   uint16_t data;
00878   uint16_t rxStatus;
00879   uint16_t rxPacketLength;
00880   uint16_t frameLength;
00881   uint16_t bytesToRead;
00882 
00883   EFM_ASSERT(buffer != NULL);
00884 
00885   while (rxFrameCount > 0)
00886   {
00887     rxFrameCount--;
00888     /* Read the received frame status */
00889     rxStatus = KSZ8851SNL_SPI_ReadRegister(RXFHSR);
00890 
00891     /* Check the consistency of the frame */
00892     if ((!(rxStatus & VALID_FRAME_MASK)) || (rxStatus & CHECKSUM_VALID_FRAME_MASK))
00893     {
00894       /* Issue the Release error frame command */
00895       ReleaseIncosistentFrame();
00896       /* continue to next frame */
00897       continue;
00898     }
00899     else
00900     {
00901       /* Read the byte size of the received frame */
00902       rxPacketLength = KSZ8851SNL_SPI_ReadRegister(RXFHBCR) & RX_BYTE_CNT_MASK;
00903 
00904       /* round to dword boundary */
00905       bytesToRead = 4 * ((rxPacketLength + 3) >> 2);
00906       LWIP_DEBUGF(NETIF_DEBUG, ("KSZ8851SNL_Receive: rxPacketLength=%u, bytesToRead=%u \n", rxPacketLength, bytesToRead));
00907       if ((bytesToRead > length) || (rxPacketLength <= 4))
00908       {
00909         /* Issue the Release error frame command */
00910         ReleaseIncosistentFrame();
00911         /* continue to next frame */
00912         continue;
00913       }
00914 
00915       /* Set QMU RXQ frame pointer to start of packet data. Note
00916        * that we skip the status word and byte count since we
00917        * already know this from RXFHSR and RXFHBCR.
00918        */
00919       KSZ8851SNL_SPI_WriteRegister(RXFDPR, 0x0004 | FD_PTR_AUTO_INC);
00920 
00921       /* Start QMU DMA transfer */
00922       data = KSZ8851SNL_SPI_ReadRegister(RXQCR) | RXQ_START_DMA;
00923       KSZ8851SNL_SPI_WriteRegister(RXQCR, data);
00924 
00925       /* Read the whole ethernet frame */
00926       KSZ8851SNL_SPI_ReadFifo(bytesToRead, buffer);
00927 
00928       /* Stop QMU DMA transfer */
00929       data = KSZ8851SNL_SPI_ReadRegister(RXQCR) & (~RXQ_START_DMA);
00930       KSZ8851SNL_SPI_WriteRegister(RXQCR, data);
00931 
00932       /* Return frame length without CRC */
00933       frameLength = rxPacketLength - 4;
00934       return frameLength;
00935     }
00936   }
00937   return 0;
00938 }
00939 
00940 /***************************************************************************/
00950 void KSZ8851SNL_MacAddressGet(uint8_t *macAddress)
00951 {
00952   int i;
00953 
00954   EFM_ASSERT(macAddress != NULL);
00955 
00956   /* set the first 3 bytes given by the EM MAC Address space */
00957   macAddress[0] = HIGH_QMU_MAC_H;
00958   macAddress[1] = HIGH_QMU_MAC_L;
00959   macAddress[2] = MID_QMU_MAC_H;
00960   /* set the next 3 bytes given by the CMU unique ID */
00961 
00962   for (i = 0; i < 3; i++)
00963   {
00964     macAddress[5 - i] = (DEVINFO->UNIQUEL & (BYTE_MASK << i * BYTE_SIZE)) >> i * BYTE_SIZE;
00965   }
00966 }
00967 
00968 /***************************************************************************/
00971 uint16_t KSZ8851SNL_PHYStatusGet(void)
00972 {
00973   return KSZ8851SNL_SPI_ReadRegister(P1SR);
00974 }