EFR32 Mighty Gecko 1 Software Documentation  efr32mg1-doc-5.1.2
ksz8851snl.c
Go to the documentation of this file.
1 /**************************************************************************/
15 #include <stdio.h>
16 
17 #include "ksz8851snl.h"
18 #include "ksz8851snl_spi.h"
19 #include "em_assert.h"
20 
21 #include "lwip/sys.h"
22 #include "lwipopts.h"
23 #include "debug.h"
24 
25 #ifndef LWIP4EFM32
26 #error "lwiopts.h for EFM32 are not included"
27 #endif
28 
29 /* Register definitions */
30 #define MARL 0x10
31 #define MARM 0x12
32 #define MARH 0x14
33 #define OBCR 0x20
34 #define GRR 0x26
35 #define TXCR 0x70
36 #define RXCR1 0x74
37 #define RXCR2 0x76
38 #define TXMIR 0x78
39 #define RXFHSR 0x7C
40 #define RXFHBCR 0x7E
41 #define TXQCR 0x80
42 #define RXQCR 0x82
43 #define TXFDPR 0x84
44 #define RXFDPR 0x86
45 #define IER 0x90
46 #define ISR 0x92
47 #define RXFCTR 0x9C
48 #define TXNTFSR 0x9E
49 #define FCLWR 0xB0
50 #define FCHWR 0xB2
51 #define CIDER 0xC0
52 #define IACR 0xC8
53 #define IADLR 0xD0
54 #define IADHR 0xD2
55 #define PMECR 0xD4
56 #define PHYRR 0xD8
57 #define P1MBCR 0xE4
58 #define P1CR 0xF6
59 #define P1SR 0xF8
61 #define KSZ8851SNL_CHIP_ID 0x8870
62 #define CHIP_ID_MASK 0xFFF0
63 #define ONE_FRAME_THRES 0x0001
64 #define FD_PTR_AUTO_INC 0x4000
65 #define CLEAR_INT 0xFFFF
66 #define NO_INT 0x0000
67 #define TX_MEM_AVAIL_MASK 0x1FFF
68 #define FRAME_ID_MASK 0x003F
69 #define CHECKSUM_VALID_FRAME_MASK 0x3C17
73 #define VALID_FRAME_MASK 0x8000
76 #define RX_BYTE_CNT_MASK 0x0FFF
77 #define LSB_MASK 0x00FF
78 #define MSB_POS 0x0008
79 #define TX_INT_on_COMPLETION 0x8000
80 #define WORD_SIZE 0x0004
81 #define EXTRA_SIZE 0x0008
82 #define BLOCKING_RECEIVE 0
83 #define WATERMARK_6KB 0x0600
84 #define WATERMARK_4KB 0x0400
85 /* Silicon Laboratories MAC address space */
86 #define HIGH_QMU_MAC_H 0x00
87 #define HIGH_QMU_MAC_L 0x0B
88 #define MID_QMU_MAC_H 0x57
89 #define BYTE_MASK 0x00FF
90 #define BYTE_SIZE 0x0008
92 /* TX Flow Control Register Options */
93 
95 #define TX_FLOW_CTRL_ICMP_CHECKSUM 0x0100
96 
97 #define TX_FLOW_CTRL_TCP_CHECKSUM 0x0040
98 
99 #define TX_FLOW_CTRL_IP_CHECKSUM 0x0020
101 #define TX_FLOW_CTRL_FLUSH_QUEUE 0x0010
103 #define TX_FLOW_CTRL_FLOW_ENABLE 0x0008
105 #define TX_FLOW_CTRL_PAD_ENABLE 0x0004
107 #define TX_FLOW_CTRL_CRC_ENABLE 0x0002
109 #define TX_FLOW_CTRL_ENABLE 0x0001
112 #define TX_FLOW_CTRL_CONFIG (TX_FLOW_CTRL_ICMP_CHECKSUM | \
113  TX_FLOW_CTRL_TCP_CHECKSUM | \
114  TX_FLOW_CTRL_IP_CHECKSUM | \
115  TX_FLOW_CTRL_FLOW_ENABLE | \
116  TX_FLOW_CTRL_PAD_ENABLE | \
117  TX_FLOW_CTRL_CRC_ENABLE)
118 
119 /* TXQ Command Register Options */
121 #define TXQ_AUTO_ENQUEUE 0x0004
122 
123 #define TXQ_MEM_AVAILABLE_INT 0x0002
125 #define TXQ_ENQUEUE 0x0001
127 
128 /* RX Flow Control Register 1 Options */
130 #define RX_FLOW_CTRL_FLUSH_QUEUE 0x8000
131 
132 #define RX_FLOW_CTRL_UDP_CHECKSUM 0x4000
134 #define RX_FLOW_CTRL_TCP_CHECKSUM 0x2000
136 #define RX_FLOW_CTRL_IP_CHECKSUM 0x1000
138 #define RX_FLOW_CTRL_MAC_FILTER 0x0800
140 #define RX_FLOW_CTRL_FLOW_ENENABLE 0x0400
142 #define RX_FLOW_CTRL_BAD_PACKET 0x0200
144 #define RX_FLOW_CTRL_BROADCAST_ENABLE 0x0080
146 #define RX_FLOW_CTRL_MULTICAST_ENABLE 0x0040
148 #define RX_FLOW_CTRL_UNICAST_ENABLE 0x0020
150 #define RX_FLOW_CTRL_PROMISCUOUS_MODE 0x0012
152 #define RX_FLOW_CTRL_RX_ALL 0x0010
154 #define RX_FLOW_CTRL_INVERSE_FILTER 0x0002
156 #define RX_FLOW_CTRL_RX_ENABLE 0x0001
159 #define RX_FLOW_CTRL1_CONFIG (RX_FLOW_CTRL_UDP_CHECKSUM | \
160  RX_FLOW_CTRL_TCP_CHECKSUM | \
161  RX_FLOW_CTRL_IP_CHECKSUM | \
162  RX_FLOW_CTRL_MAC_FILTER | \
163  RX_FLOW_CTRL_FLOW_ENENABLE | \
164  RX_FLOW_CTRL_BROADCAST_ENABLE | \
165  RX_FLOW_CTRL_UNICAST_ENABLE)
166 
167 /* RX Flow Control Register 2 Options */
168 /* SPI Receive Data Burst Length */
170 #define RX_FLOW_CTRL_BURST_LEN_MASK 0x00E0
171 
172 #define RX_FLOW_CTRL_BURST_LEN_4 0x0000
174 #define RX_FLOW_CTRL_BURST_LEN_8 0x0020
176 #define RX_FLOW_CTRL_BURST_LEN_16 0x0040
178 #define RX_FLOW_CTRL_BURST_LEN_32 0x0060
180 #define RX_FLOW_CTRL_BURST_LEN_FRAME 0x0080
182 #define RX_FLOW_CTRL_IPV6_UDP_FRAG_PASS 0x0010
184 #define RX_FLOW_CTRL_IPV6_UDP_ZERO_PASS 0x0008
186 #define RX_FLOW_CTRL_UDP_LITE_CHECKSUM 0x0004
188 #define RX_FLOW_CTRL_ICMP_CHECKSUM 0x0002
190 #define RX_FLOW_CTRL_BLOCK_MAC 0x0001
193 #define RX_FLOW_CTRL2_CONFIG (RX_FLOW_CTRL_IPV6_UDP_FRAG_PASS | \
194  RX_FLOW_CTRL_UDP_LITE_CHECKSUM | \
195  RX_FLOW_CTRL_ICMP_CHECKSUM | \
196  RX_FLOW_CTRL_BURST_LEN_FRAME)
197 
198 /* RXQ Command Register Options */
200 #define RXQ_ON_TIME_INT 0x1000
201 
202 #define RXQ_ON_BYTE_CNT_INT 0x0800
204 #define RXQ_ON_FRAME_CNT_INT 0x0400
206 #define RXQ_TWOBYTE_OFFSET 0x0200
208 #define RXQ_EN_ON_TIME_INT 0x0080
210 #define RXQ_EN_ON_BYTE_CNT_INT 0x0040
212 #define RXQ_EN_ON_FRAME_CNT_INT 0x0020
214 #define RXQ_AUTO_DEQUEUE 0x0010
216 #define RXQ_START_DMA 0x0008
218 #define RXQ_RELEASE_ERROR_FRAME 0x0001
221 #define RXQ_CMD_CONFIG (RXQ_EN_ON_FRAME_CNT_INT | \
222  RXQ_AUTO_DEQUEUE)
223 
224 /* Port 1 Status Register */
226 #define PORT1_AN_DONE 0x0040
227 
228 #define PORT1_LINK_GOOD 0x0020
230 /* Port 1 Control Register Options */
232 #define PORT1_LED_OFF 0x8000
233 
234 #define PORT1_TX_DISABLE 0x4000
236 #define PORT1_AUTO_NEG_RESTART 0x2000
238 #define PORT1_POWER_DOWN 0x0800
240 #define PORT1_AUTO_MDIX_DISABLE 0x0400
242 #define PORT1_FORCE_MDIX 0x0200
244 #define PORT1_AUTO_NEG_ENABLE 0x0080
246 #define PORT1_FORCE_100_MBIT 0x0040
248 #define PORT1_FORCE_FULL_DUPLEX 0x0020
250 #define PORT1_AUTO_NEG_FLOW_CTRL 0x0010
252 #define PORT1_AUTO_NEG_100BTX_FD 0x0008
254 #define PORT1_AUTO_NEG_100BTX 0x0004
256 #define PORT1_AUTO_NEG_10BT_FD 0x0002
258 #define PORT1_AUTO_NEG_10BT 0x0001
261 #define PORT1_CONFIG (PORT1_AUTO_NEG_ENABLE | \
262  PORT1_FORCE_100_MBIT | \
263  PORT1_FORCE_FULL_DUPLEX | \
264  PORT1_AUTO_NEG_FLOW_CTRL | \
265  PORT1_AUTO_NEG_100BTX_FD | \
266  PORT1_AUTO_NEG_100BTX | \
267  PORT1_AUTO_NEG_10BT_FD | \
268  PORT1_AUTO_NEG_10BT )
269 
270 /* Global Reset Register Options */
272 #define QMU_MODULE_SOFT_RESET 0x0002
273 
274 #define GLOBAL_SOFT_RESET 0x0001
277 #define PHY_RESET 0x0001
278 
279 /* P1MBCR register */
281 #define DIGITAL_LOOPBACK 0x4000
282 
283 #define FORCE_100 0x2000
285 #define AUTO_NEG 0x1000
287 #define RESTART_AUTO_NEG 0x0200
289 #define FORCE_FULL_DUPLEX 0x0100
292 #define TX_MEMORY_WAIT_MS 500
293 
295 #define FRAME_COUNT_THRESHOLD 1
296 
298 #define MIB_MASK 0x1C00
299 #define MIB_RxByte 0x00
300 #define MIB_XXX 0x01
301 #define MIB_RxUndersizePkt 0x02
302 #define MIB_RxFragments 0x03
303 #define MIB_RxOversize 0x04
304 #define MIB_RxJabbers 0x05
305 #define MIB_RxSymbolError 0x06
306 #define MIB_RxCRCError 0x07
307 #define MIB_RxAlignmentError 0x08
308 #define MIB_RxControl8808Pkts 0x09
309 #define MIB_RxPausePkts 0x0A
310 #define MIB_RxBroadcast 0x0B
311 #define MIB_RxMulticast 0x0C
312 #define MIB_RxUnicast 0x0D
313 #define MIB_Rx64Octets 0x0E
314 #define MIB_Rx65to127Octets 0x0F
315 #define MIB_Rx128to255Octets 0x10
316 #define MIB_Rx256to511Octets 0x11
317 #define MIB_Rx512to1023Octets 0x12
318 #define MIB_Rx1024to1521Octets 0x13
319 #define MIB_Rx1522to2000Octets 0x14
320 #define MIB_TxByte 0x15
321 #define MIB_TxLateCollision 0x16
322 #define MIB_TxPausePkts 0x17
323 #define MIB_TxBroadcastPkts 0x18
324 #define MIB_TxMulticastPkts 0x19
325 #define MIB_TxUnicastPkts 0x1A
326 #define MIB_TxDeferred 0x1B
327 #define MIB_TxTotalCollision 0x1C
328 #define MIB_TxExcessiveCollision 0x1D
329 #define MIB_TxSingleCollision 0x1E
330 #define MIB_TxMultipleCollision 0x1F
333 #define READ_UNSAFE_REGISTERS 0
334 
335 static uint16_t frameId = 0;
336 static uint8_t macAddress[6];
337 static uint16_t rxFrameCount;
338 static uint32_t interruptCnt = 0;
351 
352 /***************************************************************************/
362 static uint32_t MIBCountersRead(uint16_t offset)
363 {
364  uint16_t data;
365  uint32_t counter;
366 
367  data = MIB_MASK | offset;
370  counter |= KSZ8851SNL_SPI_ReadRegister(IADHR) << 16;
371 
372  return counter;
373 }
374 
375 /***************************************************************************/
383 {
384  mibCounters.RxByteCnt += MIBCountersRead(MIB_RxByte);
395  mibCounters.TxByteCnt += MIBCountersRead(MIB_TxByte);
402 }
403 
404 /***************************************************************************/
410 {
411  printf("####################### MIB COUNTER DUMP ########################\n");
412  printf("MIB_RxByteCnt = %lu\n", mibCounters.RxByteCnt);
413  printf("MIB_RxUndersizePktCnt = %lu\n", mibCounters.RxUndersizePktCnt);
414  printf("MIB_RxFragmentsCnt = %lu\n", mibCounters.RxFragmentsCnt);
415  printf("MIB_RxOversizeCnt = %lu\n", mibCounters.RxOversizeCnt);
416  printf("MIB_RxJabbersCnt = %lu\n", mibCounters.RxJabbersCnt);
417  printf("MIB_RxSymbolErrorCnt = %lu\n", mibCounters.RxSymbolErrorCnt);
418  printf("MIB_RxCRCErrorCnt = %lu\n", mibCounters.RxCRCErrorCnt);
419  printf("MIB_RxPausePktsCnt = %lu\n", mibCounters.RxPausePktsCnt);
420  printf("MIB_RxBroadcastCnt = %lu\n", mibCounters.RxBroadcastCnt);
421  printf("MIB_RxMulticastCnt = %lu\n", mibCounters.RxMulticastCnt);
422  printf("MIB_RxUnicastCnt = %lu\n", mibCounters.RxUnicastCnt);
423  printf("MIB_TxByteCnt = %lu\n", mibCounters.TxByteCnt);
424  printf("MIB_TxPausePktsCnt = %lu\n", mibCounters.TxPausePktsCnt);
425  printf("MIB_TxBroadcastPktsCnt = %lu\n", mibCounters.TxBroadcastPktsCnt);
426  printf("MIB_TxMulticastPktsCnt = %lu\n", mibCounters.TxMulticastPktsCnt);
427  printf("MIB_TxUnicastPktsCnt = %lu\n", mibCounters.TxUnicastPktsCnt);
428  printf("MIB_TxDeferredCnt = %lu\n", mibCounters.TxDeferredCnt);
429  printf("MIB_TxTotalCollisionCnt = %lu\n", mibCounters.TxTotalCollisionCnt);
430  printf("#################################################################\n");
431 }
432 
433 /***************************************************************************/
438 {
439  printf("###################### ALL REGISTER DUMP ########################\n");
440  int i;
441  for (i = 0x00; i < 0xFF; i += 0x02)
442  {
443  if ((i % 8 == 0) && (i > 0))
444  {
445  printf("\n");
446  }
447  printf("REG[0x%02X]=0x%04X ", i, KSZ8851SNL_SPI_ReadRegister(i));
448  }
449  printf("\n");
450  printf("#################################################################\n");
451 }
452 
453 /***************************************************************************/
457 void KSZ8851SNL_RegistersDump(void)
458 {
459  printf("##################### SPECIAL REGISTER DUMP ######################\n");
460  printf("MARL [0x%02X]=0x%04X\n", MARL, KSZ8851SNL_SPI_ReadRegister(MARL));
461  printf("MARM [0x%02X]=0x%04X\n", MARM, KSZ8851SNL_SPI_ReadRegister(MARM));
462  printf("MARH [0x%02X]=0x%04X\n", MARH, KSZ8851SNL_SPI_ReadRegister(MARH));
463  printf("OBCR [0x%02X]=0x%04X\n", OBCR, KSZ8851SNL_SPI_ReadRegister(OBCR));
464  printf("GRR [0x%02X]=0x%04X\n", GRR, KSZ8851SNL_SPI_ReadRegister(GRR));
465  printf("TXCR [0x%02X]=0x%04X\n", TXCR, KSZ8851SNL_SPI_ReadRegister(TXCR));
466  printf("RXCR1 [0x%02X]=0x%04X\n", RXCR1, KSZ8851SNL_SPI_ReadRegister(RXCR1));
467  printf("RXCR2 [0x%02X]=0x%04X\n", RXCR2, KSZ8851SNL_SPI_ReadRegister(RXCR2));
468  printf("TXMIR [0x%02X]=0x%04X\n", TXMIR, KSZ8851SNL_SPI_ReadRegister(TXMIR));
469 #if (READ_UNSAFE_REGISTERS)
470  printf("RXFHSR[0x%02X]=0x%04X\n", RXFHSR, KSZ8851SNL_SPI_ReadRegister(RXFHSR));
471 #endif
472  printf("TXQCR [0x%02X]=0x%04X\n", TXQCR, KSZ8851SNL_SPI_ReadRegister(TXQCR));
473  printf("RXQCR [0x%02X]=0x%04X\n", RXQCR, KSZ8851SNL_SPI_ReadRegister(RXQCR));
474  printf("TXFDPR[0x%02X]=0x%04X\n", TXFDPR, KSZ8851SNL_SPI_ReadRegister(TXFDPR));
475  printf("RXFDPR[0x%02X]=0x%04X\n", RXFDPR, KSZ8851SNL_SPI_ReadRegister(RXFDPR));
476  printf("IER [0x%02X]=0x%04X\n", IER, KSZ8851SNL_SPI_ReadRegister(IER));
477  printf("ISR [0x%02X]=0x%04X\n", ISR, KSZ8851SNL_SPI_ReadRegister(ISR));
478  printf("RXFCTR[0x%02X]=0x%04X\n", RXFCTR, KSZ8851SNL_SPI_ReadRegister(RXFCTR));
479 #if (READ_UNSAFE_REGISTERS)
480  printf("TXNTFSR[0x%02X]=0x%04X\n", TXNTFSR, KSZ8851SNL_SPI_ReadRegister(TXNTFSR));
481 #endif
482  printf("CIDER [0x%02X]=0x%04X\n", CIDER, KSZ8851SNL_SPI_ReadRegister(CIDER));
483  printf("PHYRR [0x%02X]=0x%04X\n", PHYRR, KSZ8851SNL_SPI_ReadRegister(PHYRR));
484  printf("P1MBCR[0x%02X]=0x%04X\n", P1MBCR, KSZ8851SNL_SPI_ReadRegister(P1MBCR));
485  printf("P1CR [0x%02X]=0x%04X\n", P1CR, KSZ8851SNL_SPI_ReadRegister(P1CR));
486  printf("#################################################################\n");
487 }
488 
489 /**************************************************************************/
492 void KSZ8851SNL_IntEnable(void)
493 {
494  if (interruptCnt)
495  {
496  interruptCnt--;
497  }
498  if (interruptCnt == 0)
499  {
500  /* Enable interrupts */
502  }
503 }
504 
505 /**************************************************************************/
508 void KSZ8851SNL_IntDisable(void)
509 {
511  interruptCnt++;
512 }
513 
514 /**************************************************************************/
521 void KSZ8851SNL_IntClear(uint16_t flags)
522 {
524 }
525 
526 /**************************************************************************/
529 uint16_t KSZ8851SNL_IntGet(void)
530 {
532 }
533 
534 /**************************************************************************/
541 void KSZ8851SNL_PMECRStatusClear(uint16_t flags)
542 {
543  uint16_t status = KSZ8851SNL_SPI_ReadRegister(PMECR) | flags;
545 }
546 
547 /**************************************************************************/
550 uint16_t KSZ8851SNL_RXQCRGet(void)
551 {
553 }
554 
555 /**************************************************************************/
559 {
560  /* Read the frame count and threshold register */
562  /* Extract the actual number of frames from RX_FRAME_THRES_REG*/
563  rxFrameCount = rxftr >> MSB_POS;
564 }
565 
566 /**************************************************************************/
569 void KSZ8851SNL_TxQueueReset(void)
570 {
571  uint16_t data;
574  /* Disable TX */
575  data &= ~TX_FLOW_CTRL_ENABLE;
577  /* Flush */
578  data |= TX_FLOW_CTRL_FLUSH_QUEUE;
580  /* normal op - no flush */
581  data &= ~TX_FLOW_CTRL_FLUSH_QUEUE;
583  /* Enable TX */
584  data |= TX_FLOW_CTRL_ENABLE;
586 }
587 
588 /**************************************************************************/
591 void KSZ8851SNL_RxQueueReset(void)
592 {
593  uint16_t data;
596  /* Disable RX */
597  data &= ~RX_FLOW_CTRL_RX_ENABLE;
599  /* Flush */
601  /* Clear flush */
602  data &= ~RX_FLOW_CTRL_FLUSH_QUEUE;
604  /* Write default config with enable set */
605  data |= RX_FLOW_CTRL_RX_ENABLE;
607 }
608 
609 /**************************************************************************/
612 uint16_t KSZ8851SNL_FrameCounterGet(void)
613 {
614  return rxFrameCount;
615 }
616 
617 /***************************************************************************/
620 void KSZ8851SNL_Init(void)
621 {
622  uint16_t data;
624  /* Initialize SPI Interface */
626 
627  /* Reset PHY module */
629 
630  /* Reset Soft (clear registers of PHY, MAC, QMU, DMA) */
632  data &= ~GLOBAL_SOFT_RESET;
634 
635  /* Reset Soft (clear registers of PHY, MAC, QMU, DMA) */
637  data &= ~GLOBAL_SOFT_RESET;
639 
640  /* Read the chip ID and check if that is correct */
642 
643  /* The CIDER lower bits [3..1] are defined as revision number,
644  * thus a mask needs to be applied
645  */
646 
647  /* this is a hard assert - abort */
648  EFM_ASSERT((data & CHIP_ID_MASK) == KSZ8851SNL_CHIP_ID);
649 
650  /* Write the Queue Management Unit MAC Address */
651  KSZ8851SNL_MacAddressGet(macAddress);
652  /* Write the MAC Address into the MAC registers */
653  KSZ8851SNL_SPI_WriteRegister(MARH, (macAddress[0] << 8) | macAddress[1]);
654  KSZ8851SNL_SPI_WriteRegister(MARM, (macAddress[2] << 8) | macAddress[3]);
655  KSZ8851SNL_SPI_WriteRegister(MARL, (macAddress[4] << 8) | macAddress[5]);
656 
657  /* Enable QMU Transmit Frame Data Pointer Auto Increment */
659 
660  /* Enable QMU Transmit:
661  * flow control,
662  * padding,
663  * CRC,
664  * checksum generation.
665  */
667 
668  /* Enable QMU Receive Frame Data Pointer Auto Increment */
670 
671  /* Configure Receive Frame Threshold for one frame */
673 
674  /* Set RX queue low watermark to 10240 bytes for issuing of
675  stop PAUSE frames (flow control) */
676  data = 0xA00;
678 
679  /* Enable QMU Receive:
680  * flow control,
681  * receive all broadcast frame,
682  * receive unicast frame,
683  * IP/TCP/UDP/ICMP checksum generation.
684  */
686 
687  /* Enable QMU Receive:
688  * ICMP/UDP Lite frame checksum verification,
689  * UDP Lite frame checksum generation,
690  * IPv6 UDP fragment frame pass.
691  */
693 
694  /* Enable QMU Receive:
695  * IP Header Two-Byte Offset,
696  * Receive Frame Count Threshold,
697  * RXQ Auto-Dequeue frame.
698  */
700 
701  /* Restart Port 1 auto-negotiation */
703 
704  /* Clear interrupts */
706 }
707 
708 
709 /***************************************************************************/
712 void KSZ8851SNL_Enable(void)
713 {
714  uint16_t data;
717 
718  /* Enable QMU Transmit */
720  data |= TX_FLOW_CTRL_ENABLE;
722 
723  /* Enable QMU Receive */
725  data |= RX_FLOW_CTRL_RX_ENABLE;
727 }
728 
729 
730 /***************************************************************************/
741 bool KSZ8851SNL_TransmitBegin(uint16_t length)
742 {
743  uint16_t txmir;
744  uint16_t data, reqSize;
745  uint8_t outbuf[4];
746 
747  /* Wait for previous frame to finish before setting up a new one */
749  {
750  ;
751  }
752 
753  /* Make sure there is room for
754  *
755  * 4 bytes Control Word
756  * 4 bytes Byte Count
757  * n bytes Packet
758  * 4 bytes CRC
759  */
760  reqSize = length + 12;
762  LWIP_DEBUGF(NETIF_DEBUG, ("KSZ8851SNL_LongTransmitInit: txmir =%hu reqSize = %hu \n", txmir, reqSize));
763 
764  if (txmir < reqSize)
765  {
766  /* TXQ is out of memory */
767  LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_LEVEL_WARNING, ("Not enough TXQ Memory, available=%u required=%u\n", txmir, reqSize));
768  return false;
769  }
770 
771  LWIP_DEBUGF(NETIF_DEBUG, ("KSZ8851SNL_LongTransmitInit: Memory available > txmir =%hu reqSize = %hu \n", txmir, reqSize));
772  /* Enable TXQ write access */
775 
776  /* Write frame ID, control word and byte count */
777  outbuf[0] = (frameId++ & FRAME_ID_MASK);
778  outbuf[1] = 0x80; /* TX_INT_on_COMPLETION */
779  outbuf[2] = length & LSB_MASK;
780  outbuf[3] = length >> MSB_POS;
781 
782  /* Start the SPI Transfer and send frame header */
784  KSZ8851SNL_SPI_WriteFifo(4, outbuf);
785 
786  return true;
787 }
788 
789 
790 /***************************************************************************/
805 void KSZ8851SNL_Transmit(uint16_t length, const uint8_t *buffer)
806 {
807  EFM_ASSERT(buffer != NULL);
808  KSZ8851SNL_SPI_WriteFifo(length, buffer);
809 }
810 
811 /***************************************************************************/
823 void KSZ8851SNL_TransmitEnd(uint16_t length)
824 {
825  uint16_t data;
826  uint16_t padding;
827  uint8_t dummy[4] = {0x00};
828 
829  /* Padding packet to 4 byte boundary */
830  if (length % 4)
831  {
832  padding = 4 - (length % 4);
833  KSZ8851SNL_SPI_WriteFifo(padding, dummy);
834  }
835 
836  /* Stop the SPI Transfer */
838 
839  /* Disable TXQ write access */
842 
843  /* Start TXQ Manual enqueue */
846 }
847 
848 /***************************************************************************/
852 static void ReleaseIncosistentFrame(void)
853 {
854  uint16_t data;
855  /* Issue the Release error frame command */
858 
859  /* Wait for PHY to clear the command/flag */
861  {
862  ;
863  }
864 }
865 
866 /***************************************************************************/
879 uint16_t KSZ8851SNL_Receive(uint16_t length, uint8_t *buffer)
880 {
881  uint16_t data;
882  uint16_t rxStatus;
883  uint16_t rxPacketLength;
884  uint16_t frameLength;
885  uint16_t bytesToRead;
886 
887  EFM_ASSERT(buffer != NULL);
888 
889  while (rxFrameCount > 0)
890  {
891  rxFrameCount--;
892  /* Read the received frame status */
894 
895  /* Check the consistency of the frame */
896  if ((!(rxStatus & VALID_FRAME_MASK)) || (rxStatus & CHECKSUM_VALID_FRAME_MASK))
897  {
898  /* Issue the Release error frame command */
900  /* continue to next frame */
901  continue;
902  }
903  else
904  {
905  /* Read the byte size of the received frame */
907 
908  /* round to dword boundary */
909  bytesToRead = 4 * ((rxPacketLength + 3) >> 2);
910  LWIP_DEBUGF(NETIF_DEBUG, ("KSZ8851SNL_Receive: rxPacketLength=%u, bytesToRead=%u \n", rxPacketLength, bytesToRead));
911  if ((bytesToRead > length) || (rxPacketLength <= 4))
912  {
913  /* Issue the Release error frame command */
915  /* continue to next frame */
916  continue;
917  }
918 
919  /* Set QMU RXQ frame pointer to start of packet data. Note
920  * that we skip the status word and byte count since we
921  * already know this from RXFHSR and RXFHBCR.
922  */
924 
925  /* Start QMU DMA transfer */
928 
929  /* Read the whole ethernet frame */
930  KSZ8851SNL_SPI_ReadFifo(bytesToRead, buffer);
931 
932  /* Stop QMU DMA transfer */
935 
936  /* Return frame length without CRC */
937  frameLength = rxPacketLength - 4;
938  return frameLength;
939  }
940  }
941  return 0;
942 }
943 
944 /***************************************************************************/
954 void KSZ8851SNL_MacAddressGet(uint8_t *macAddress)
955 {
956  int i;
958  EFM_ASSERT(macAddress != NULL);
959 
960  /* set the first 3 bytes given by the EM MAC Address space */
961  macAddress[0] = HIGH_QMU_MAC_H;
962  macAddress[1] = HIGH_QMU_MAC_L;
963  macAddress[2] = MID_QMU_MAC_H;
964  /* set the next 3 bytes given by the CMU unique ID */
965 
966  for (i = 0; i < 3; i++)
967  {
968  macAddress[5 - i] = (DEVINFO->UNIQUEL & (BYTE_MASK << i * BYTE_SIZE)) >> i * BYTE_SIZE;
969  }
970 }
971 
972 /***************************************************************************/
975 uint16_t KSZ8851SNL_PHYStatusGet(void)
976 {
978 }
uint32_t RxFragmentsCnt
Definition: ksz8851snl.h:86
#define RX_FLOW_CTRL_RX_ENABLE
Definition: ksz8851snl.c:159
#define PMECR
Definition: ksz8851snl.c:55
void KSZ8851SNL_Enable(void)
Enable RX and TX.
Definition: ksz8851snl.c:715
static uint32_t MIBCountersRead(uint16_t offset)
helper function for KSZ8851SNL_UpdateMIBCounters
Definition: ksz8851snl.c:365
#define KSZ8851SNL_CHIP_ID
Definition: ksz8851snl.c:61
static void ReleaseIncosistentFrame(void)
Release the current frame if it is inconsistent.
Definition: ksz8851snl.c:855
#define MARM
Definition: ksz8851snl.c:31
#define ISR
Definition: ksz8851snl.c:46
SPI interface API for KSZ8851SNL Ethernet controller.
Emlib peripheral API "assert" implementation.
static KSZ8851SLN_mib_t mibCounters
Copy of the current MIB counters values from the ksz8851snl. This is updated by calling KSZ8851SNL_MI...
Definition: ksz8851snl.c:353
void KSZ8851SNL_IntDisable(void)
disables the chip interrupts
Definition: ksz8851snl.c:511
uint32_t RxUnicastCnt
Definition: ksz8851snl.h:104
#define FD_PTR_AUTO_INC
Definition: ksz8851snl.c:64
#define MIB_TxByte
Definition: ksz8851snl.c:323
void KSZ8851SNL_MacAddressGet(uint8_t *macAddress)
Get the MAC address of the current board.
Definition: ksz8851snl.c:957
#define MIB_TxMulticastPkts
Definition: ksz8851snl.c:327
#define TXQCR
Definition: ksz8851snl.c:41
#define HIGH_QMU_MAC_H
Definition: ksz8851snl.c:89
void KSZ8851SNL_IntClear(uint16_t flags)
Clear interrupt flags.
Definition: ksz8851snl.c:524
#define CHECKSUM_VALID_FRAME_MASK
Definition: ksz8851snl.c:69
#define RXFCTR
Definition: ksz8851snl.c:47
#define MID_QMU_MAC_H
Definition: ksz8851snl.c:91
#define MIB_TxUnicastPkts
Definition: ksz8851snl.c:328
#define RXFDPR
Definition: ksz8851snl.c:44
#define RXQ_RELEASE_ERROR_FRAME
Definition: ksz8851snl.c:221
#define MIB_RxByte
Definition: ksz8851snl.c:302
#define FRAME_ID_MASK
Definition: ksz8851snl.c:68
#define NO_INT
Definition: ksz8851snl.c:66
#define RXFHSR
Definition: ksz8851snl.c:39
uint32_t TxMulticastPktsCnt
Definition: ksz8851snl.h:112
uint32_t RxCRCErrorCnt
Definition: ksz8851snl.h:96
void KSZ8851SNL_RxQueueReset(void)
Reset RxQueue.
Definition: ksz8851snl.c:594
void KSZ8851SNL_Init(void)
Initialize the registers of the ethernet controller.
Definition: ksz8851snl.c:623
#define TX_FLOW_CTRL_CONFIG
Definition: ksz8851snl.c:115
#define PORT1_AUTO_NEG_RESTART
Definition: ksz8851snl.c:239
void KSZ8851SNL_TxQueueReset(void)
Reset TxQueue.
Definition: ksz8851snl.c:572
void KSZ8851SNL_SPI_WriteFifo(int numBytes, const uint8_t *data)
Continue writing ethernet controller FIFO.
#define MARL
Definition: ksz8851snl.c:30
#define TXQ_ENQUEUE
Definition: ksz8851snl.c:128
void KSZ8851SNL_AllRegistersDump(void)
Prints the value of the registers of the ethernet controller.
Definition: ksz8851snl.c:440
uint32_t RxUndersizePktCnt
Definition: ksz8851snl.h:84
#define CIDER
Definition: ksz8851snl.c:51
#define MIB_RxUndersizePkt
Definition: ksz8851snl.c:304
#define MIB_RxSymbolError
Definition: ksz8851snl.c:308
#define TXCR
Definition: ksz8851snl.c:35
#define RX_FLOW_CTRL2_CONFIG
Definition: ksz8851snl.c:196
uint32_t TxBroadcastPktsCnt
Definition: ksz8851snl.h:110
#define RXCR1
Definition: ksz8851snl.c:36
#define HIGH_QMU_MAC_L
Definition: ksz8851snl.c:90
uint16_t KSZ8851SNL_SPI_ReadRegister(uint8_t reg)
Read ethernet controller register.
#define GLOBAL_SOFT_RESET
Definition: ksz8851snl.c:277
uint32_t RxPausePktsCnt
Definition: ksz8851snl.h:98
uint16_t KSZ8851SNL_PHYStatusGet(void)
Get the PHY status.
Definition: ksz8851snl.c:978
uint32_t RxJabbersCnt
Definition: ksz8851snl.h:91
#define RX_FLOW_CTRL1_CONFIG
Definition: ksz8851snl.c:162
Driver for Micrel KSZ8851SNL Ethernet controller.
void KSZ8851SNL_FrameCounterSet(void)
FrameCounter.
Definition: ksz8851snl.c:561
uint32_t TxUnicastPktsCnt
Definition: ksz8851snl.h:114
bool KSZ8851SNL_TransmitBegin(uint16_t length)
Prepares for a transmission of an ethernet frame over the network.
Definition: ksz8851snl.c:744
#define MSB_POS
Definition: ksz8851snl.c:81
uint16_t KSZ8851SNL_FrameCounterGet(void)
FrameCounter.
Definition: ksz8851snl.c:615
void KSZ8851SNL_SPI_WriteFifoEnd(void)
Stop read/write the ethernet controller FIFO.
void KSZ8851SNL_MIBCountersDump(void)
Dumps the Management Information Base Counters.
Definition: ksz8851snl.c:412
void KSZ8851SNL_RegistersDump(void)
Prints the value of the registers of the ethernet controller.
Definition: ksz8851snl.c:460
#define RXQ_START_DMA
Definition: ksz8851snl.c:219
#define DEVINFO
void KSZ8851SNL_MIBCountersUpdate(void)
Update the Management Information Base Counters.
Definition: ksz8851snl.c:385
#define CHIP_ID_MASK
Definition: ksz8851snl.c:62
void KSZ8851SNL_TransmitEnd(uint16_t length)
Ends a transmission of an ethernet frame to the ethernet controller.
Definition: ksz8851snl.c:826
uint32_t RxOversizeCnt
Definition: ksz8851snl.h:88
#define CLEAR_INT
Definition: ksz8851snl.c:65
uint32_t RxBroadcastCnt
Definition: ksz8851snl.h:100
uint16_t KSZ8851SNL_Receive(uint16_t length, uint8_t *buffer)
Performs the actual receive of a raw frame over the network.
Definition: ksz8851snl.c:882
#define TX_FLOW_CTRL_FLUSH_QUEUE
Definition: ksz8851snl.c:104
#define MARH
Definition: ksz8851snl.c:32
#define MIB_TxBroadcastPkts
Definition: ksz8851snl.c:326
#define TX_MEM_AVAIL_MASK
Definition: ksz8851snl.c:67
#define FCLWR
Definition: ksz8851snl.c:49
void KSZ8851SNL_SPI_ReadFifo(int numBytes, uint8_t *data)
Read data from the ethernet controller RX FIFO.
#define RX_FLOW_CTRL_FLUSH_QUEUE
Definition: ksz8851snl.c:133
#define RXCR2
Definition: ksz8851snl.c:37
uint32_t RxSymbolErrorCnt
Definition: ksz8851snl.h:93
#define MIB_RxFragments
Definition: ksz8851snl.c:305
#define RXQCR
Definition: ksz8851snl.c:42
#define RXQ_CMD_CONFIG
Definition: ksz8851snl.c:224
#define MIB_TxTotalCollision
Definition: ksz8851snl.c:330
void KSZ8851SNL_Transmit(uint16_t length, const uint8_t *buffer)
Transmit a chunk of data to the ethernet controller. The chunk can be either a full ethernet frame or...
Definition: ksz8851snl.c:808
#define TX_FLOW_CTRL_ENABLE
Definition: ksz8851snl.c:112
uint16_t KSZ8851SNL_RXQCRGet(void)
Get RXQCR register.
Definition: ksz8851snl.c:553
#define MIB_MASK
Definition: ksz8851snl.c:301
#define TXMIR
Definition: ksz8851snl.c:38
#define LSB_MASK
Definition: ksz8851snl.c:80
void KSZ8851SNL_IntEnable(void)
enables the chip interrupts
Definition: ksz8851snl.c:495
#define MIB_RxJabbers
Definition: ksz8851snl.c:307
#define RXFHBCR
Definition: ksz8851snl.c:40
uint32_t TxTotalCollisionCnt
Definition: ksz8851snl.h:119
#define P1SR
Definition: ksz8851snl.c:59
uint32_t RxMulticastCnt
Definition: ksz8851snl.h:102
void KSZ8851SNL_SPI_Init(void)
KSZ8851SNL_SPI_Init Initialize SPI interface to Ethernet controller.
void KSZ8851SNL_PMECRStatusClear(uint16_t flags)
Clear PMECR (Power Management Event Control Register) flags.
Definition: ksz8851snl.c:544
#define IADLR
Definition: ksz8851snl.c:53
#define TXNTFSR
Definition: ksz8851snl.c:48
#define MIB_RxUnicast
Definition: ksz8851snl.c:315
#define PORT1_CONFIG
Definition: ksz8851snl.c:264
void KSZ8851SNL_SPI_WriteRegister(uint8_t reg, uint16_t value)
Write ethernet controller register.
#define MIB_RxPausePkts
Definition: ksz8851snl.c:312
#define KSZ8851SNL_INT_ENABLE_MASK
Definition: ksz8851snl.h:68
#define TXFDPR
Definition: ksz8851snl.c:43
#define MIB_RxBroadcast
Definition: ksz8851snl.c:313
#define MIB_RxMulticast
Definition: ksz8851snl.c:314
#define IACR
Definition: ksz8851snl.c:52
#define MIB_RxOversize
Definition: ksz8851snl.c:306
#define IER
Definition: ksz8851snl.c:45
#define MIB_TxDeferred
Definition: ksz8851snl.c:329
uint32_t TxPausePktsCnt
Definition: ksz8851snl.h:108
#define MIB_RxCRCError
Definition: ksz8851snl.c:309
uint16_t KSZ8851SNL_IntGet(void)
Get interrupt flags.
Definition: ksz8851snl.c:532
uint32_t TxByteCnt
Definition: ksz8851snl.h:106
#define VALID_FRAME_MASK
Definition: ksz8851snl.c:75
The MIB (Management Information Base) Counters that the ksz8851snl device expose to the host...
Definition: ksz8851snl.h:79
void KSZ8851SNL_SPI_WriteFifoBegin(void)
Start writing to the ethernet controller FIFO.
#define P1CR
Definition: ksz8851snl.c:58
#define P1MBCR
Definition: ksz8851snl.c:57
#define PHY_RESET
Definition: ksz8851snl.c:280
#define PHYRR
Definition: ksz8851snl.c:56
#define IADHR
Definition: ksz8851snl.c:54
uint32_t RxByteCnt
Definition: ksz8851snl.h:82
#define GRR
Definition: ksz8851snl.c:34
#define OBCR
Definition: ksz8851snl.c:33
uint32_t TxDeferredCnt
Definition: ksz8851snl.h:117
#define MIB_TxPausePkts
Definition: ksz8851snl.c:325
#define RX_BYTE_CNT_MASK
Definition: ksz8851snl.c:79
#define BYTE_SIZE
Definition: ksz8851snl.c:93
#define FRAME_COUNT_THRESHOLD
Definition: ksz8851snl.c:298