ksz8895_driver.c
Go to the documentation of this file.
1 /**
2  * @file ksz8895_driver.c
3  * @brief KSZ8895 5-port Ethernet switch
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2019 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 1.9.6
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "core/ethernet_misc.h"
38 #include "debug.h"
39 
40 
41 /**
42  * @brief KSZ8895 Ethernet switch driver
43  **/
44 
46 {
54 };
55 
56 
57 /**
58  * @brief Tail tag rules (host to KSZ8895)
59  **/
60 
61 const uint8_t ksz8895IngressTailTag[5] =
62 {
63  0,
68 };
69 
70 
71 /**
72  * @brief KSZ8895 Ethernet switch initialization
73  * @param[in] interface Underlying network interface
74  * @return Error code
75  **/
76 
78 {
79  uint_t port;
80  uint8_t temp;
81 
82  //Debug message
83  TRACE_INFO("Initializing KSZ8895...\r\n");
84 
85  //SPI slave mode?
86  if(interface->spiDriver != NULL)
87  {
88  //Initialize SPI
89  interface->spiDriver->init();
90  }
91 
92  //Wait for the serial interface to be ready
93  do
94  {
95  //Read CHIP_ID0 register
96  temp = ksz8895ReadSwitchReg(interface, KSZ8895_CHIP_ID0);
97 
98  //The returned data is invalid until the serial interface is ready
99  } while(temp != KSZ8895_CHIP_ID0_FAMILY_ID_DEFAULT);
100 
101 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
102  //Tail tagging mode?
103  if(interface->port != 0)
104  {
105  //Enable tail tag feature
106  temp = ksz8895ReadSwitchReg(interface, KSZ8895_GLOBAL_CTRL10);
109 
110  //Loop through ports
112  {
113  //Disable packet transmission and switch address learning
114  temp = ksz8895ReadSwitchReg(interface, KSZ8895_PORTn_CTRL2(port));
119  }
120  }
121  else
122 #endif
123  {
124  //Disable tail tag feature
125  temp = ksz8895ReadSwitchReg(interface, KSZ8895_GLOBAL_CTRL10);
128 
129  //Loop through ports
131  {
132  //Enable transmission, reception and switch address learning
133  temp = ksz8895ReadSwitchReg(interface, KSZ8895_PORTn_CTRL2(port));
138  }
139  }
140 
141  //Start switch operation
144 
145  //Dump switch registers for debugging purpose
146  ksz8895DumpSwitchReg(interface);
147 
148  //SMI interface mode?
149  if(interface->spiDriver == NULL)
150  {
151  //Loop through ports
153  {
154  //Debug message
155  TRACE_DEBUG("Port %u:\r\n", port);
156  //Dump PHY registers for debugging purpose
157  ksz8895DumpPhyReg(interface, port);
158  }
159  }
160 
161  //Force the TCP/IP stack to poll the link state at startup
162  interface->phyEvent = TRUE;
163  //Notify the TCP/IP stack of the event
165 
166  //Successful initialization
167  return NO_ERROR;
168 }
169 
170 
171 /**
172  * @brief Get link state
173  * @param[in] interface Underlying network interface
174  * @param[in] port Port number
175  * @return Link state
176  **/
177 
179 {
180  uint16_t status;
181  bool_t linkState;
182 
183  //Check port number
184  if(port >= KSZ8895_PORT1 && port <= KSZ8895_PORT4)
185  {
186  //Get exclusive access
188  //Read port status 1 register
189  status = ksz8895ReadSwitchReg(interface, KSZ8895_PORTn_STAT1(port));
190  //Release exclusive access
192 
193  //Retrieve current link state
194  linkState = (status & KSZ8895_PORTn_STAT1_LINK_GOOD) ? TRUE : FALSE;
195  }
196  else
197  {
198  //The specified port number is not valid
199  linkState = FALSE;
200  }
201 
202  //Return link status
203  return linkState;
204 }
205 
206 
207 /**
208  * @brief KSZ8895 timer handler
209  * @param[in] interface Underlying network interface
210  **/
211 
212 void ksz8895Tick(NetInterface *interface)
213 {
214  uint_t port;
215  uint16_t status;
216  bool_t linkState;
217 
218 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
219  //Tail tagging mode?
220  if(interface->port != 0)
221  {
222  uint_t i;
223  NetInterface *virtualInterface;
224 
225  //Loop through network interfaces
226  for(i = 0; i < NET_INTERFACE_COUNT; i++)
227  {
228  //Point to the current interface
229  virtualInterface = &netInterface[i];
230 
231  //Check whether the current virtual interface is attached to the
232  //physical interface
233  if(virtualInterface == interface || virtualInterface->parent == interface)
234  {
235  //The tail tag is used to indicate the source/destination port
236  port = virtualInterface->port;
237 
238  //Valid port?
239  if(port >= KSZ8895_PORT1 && port <= KSZ8895_PORT4)
240  {
241  //Read port status 1 register
242  status = ksz8895ReadSwitchReg(interface,
244 
245  //Retrieve current link state
246  linkState = (status & KSZ8895_PORTn_STAT1_LINK_GOOD) ? TRUE : FALSE;
247 
248  //Link up or link down event?
249  if(linkState != virtualInterface->linkState)
250  {
251  //Set event flag
252  interface->phyEvent = TRUE;
253  //Notify the TCP/IP stack of the event
255  }
256  }
257  }
258  }
259  }
260  else
261 #endif
262  {
263  //Initialize link state
264  linkState = FALSE;
265 
266  //Loop through ports
268  {
269  //Read port status 1 register
270  status = ksz8895ReadSwitchReg(interface, KSZ8895_PORTn_STAT1(port));
271 
272  //Retrieve current link state
273  if(status & KSZ8895_PORTn_STAT1_LINK_GOOD)
274  linkState = TRUE;
275  }
276 
277  //Link up or link down event?
278  if(linkState != interface->linkState)
279  {
280  //Set event flag
281  interface->phyEvent = TRUE;
282  //Notify the TCP/IP stack of the event
284  }
285  }
286 }
287 
288 
289 /**
290  * @brief Enable interrupts
291  * @param[in] interface Underlying network interface
292  **/
293 
295 {
296 }
297 
298 
299 /**
300  * @brief Disable interrupts
301  * @param[in] interface Underlying network interface
302  **/
303 
305 {
306 }
307 
308 
309 /**
310  * @brief KSZ8895 event handler
311  * @param[in] interface Underlying network interface
312  **/
313 
315 {
316  uint_t port;
317  uint16_t status;
318  bool_t linkState;
319 
320 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
321  //Tail tagging mode?
322  if(interface->port != 0)
323  {
324  uint_t i;
325  NetInterface *virtualInterface;
326 
327  //Loop through network interfaces
328  for(i = 0; i < NET_INTERFACE_COUNT; i++)
329  {
330  //Point to the current interface
331  virtualInterface = &netInterface[i];
332 
333  //Check whether the current virtual interface is attached to the
334  //physical interface
335  if(virtualInterface == interface ||
336  virtualInterface->parent == interface)
337  {
338  //The tail tag is used to indicate the source/destination port
339  port = virtualInterface->port;
340 
341  //Valid port?
342  if(port >= KSZ8895_PORT1 && port <= KSZ8895_PORT4)
343  {
344  //Read port status 1 register
345  status = ksz8895ReadSwitchReg(interface,
347 
348  //Retrieve current link state
349  linkState = (status & KSZ8895_PORTn_STAT1_LINK_GOOD) ? TRUE : FALSE;
350 
351  //Link up event?
352  if(linkState && !virtualInterface->linkState)
353  {
354  //Adjust MAC configuration parameters for proper operation
355  interface->linkSpeed = NIC_LINK_SPEED_100MBPS;
356  interface->duplexMode = NIC_FULL_DUPLEX_MODE;
357  interface->nicDriver->updateMacConfig(interface);
358 
359  //Read port status 2 register
360  status = ksz8895ReadSwitchReg(interface,
362 
363  //Check current operation mode
364  switch(status & KSZ8895_PORTn_CTRL7_STAT2_OP_MODE)
365  {
366  //10BASE-T half-duplex
368  virtualInterface->linkSpeed = NIC_LINK_SPEED_10MBPS;
369  virtualInterface->duplexMode = NIC_HALF_DUPLEX_MODE;
370  break;
371  //10BASE-T full-duplex
373  virtualInterface->linkSpeed = NIC_LINK_SPEED_10MBPS;
374  virtualInterface->duplexMode = NIC_FULL_DUPLEX_MODE;
375  break;
376  //100BASE-TX half-duplex
378  virtualInterface->linkSpeed = NIC_LINK_SPEED_100MBPS;
379  virtualInterface->duplexMode = NIC_HALF_DUPLEX_MODE;
380  break;
381  //100BASE-TX full-duplex
383  virtualInterface->linkSpeed = NIC_LINK_SPEED_100MBPS;
384  virtualInterface->duplexMode = NIC_FULL_DUPLEX_MODE;
385  break;
386  //Unknown operation mode
387  default:
388  //Debug message
389  TRACE_WARNING("Invalid operation mode!\r\n");
390  break;
391  }
392 
393  //Update link state
394  virtualInterface->linkState = TRUE;
395 
396  //Process link state change event
397  nicNotifyLinkChange(virtualInterface);
398  }
399  //Link down event
400  else if(!linkState && virtualInterface->linkState)
401  {
402  //Update link state
403  virtualInterface->linkState = FALSE;
404 
405  //Process link state change event
406  nicNotifyLinkChange(virtualInterface);
407  }
408  }
409  }
410  }
411  }
412  else
413 #endif
414  {
415  //Initialize link state
416  linkState = FALSE;
417 
418  //Loop through ports
420  {
421  //Read port status 1 register
422  status = ksz8895ReadSwitchReg(interface, KSZ8895_PORTn_STAT1(port));
423 
424  //Retrieve current link state
425  if(status & KSZ8895_PORTn_STAT1_LINK_GOOD)
426  linkState = TRUE;
427  }
428 
429  //Link up event?
430  if(linkState)
431  {
432  //Adjust MAC configuration parameters for proper operation
433  interface->linkSpeed = NIC_LINK_SPEED_100MBPS;
434  interface->duplexMode = NIC_FULL_DUPLEX_MODE;
435  interface->nicDriver->updateMacConfig(interface);
436 
437  //Update link state
438  interface->linkState = TRUE;
439  }
440  else
441  {
442  //Update link state
443  interface->linkState = FALSE;
444  }
445 
446  //Process link state change event
447  nicNotifyLinkChange(interface);
448  }
449 }
450 
451 
452 /**
453  * @brief Add tail tag to Ethernet frame
454  * @param[in] interface Underlying network interface
455  * @param[in] buffer Multi-part buffer containing the payload
456  * @param[in,out] offset Offset to the first payload byte
457  * @param[in] port Switch port identifier
458  * @param[in,out] type Ethernet type
459  * @return Error code
460  **/
461 
463  size_t *offset, uint8_t port, uint16_t *type)
464 {
465 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
466  error_t error;
467  size_t length;
468  const uint8_t *tailTag;
469 
470  //Valid port?
471  if(port >= KSZ8895_PORT1 && port <= KSZ8895_PORT4)
472  {
473  //The one byte tail tagging is used to indicate the destination port
474  tailTag = &ksz8895IngressTailTag[port];
475 
476  //Retrieve the length of the frame
477  length = netBufferGetLength(buffer) - *offset;
478 
479  //The host controller should manually add padding to the packet before
480  //inserting the tail tag
481  error = ethPadFrame(buffer, &length);
482 
483  //Check status code
484  if(!error)
485  {
486  //The tail tag is inserted at the end of the packet, just before the CRC
487  error = netBufferAppend(buffer, tailTag, sizeof(uint8_t));
488  }
489  }
490  else
491  {
492  //Invalid port identifier
493  error = ERROR_WRONG_IDENTIFIER;
494  }
495 
496  //Return status code
497  return error;
498 #else
499  //Tail tagging mode is not implemented
500  return NO_ERROR;
501 #endif
502 }
503 
504 
505 /**
506  * @brief Decode tail tag from incoming Ethernet frame
507  * @param[in] interface Underlying network interface
508  * @param[in,out] frame Pointer to the received Ethernet frame
509  * @param[in,out] length Length of the frame, in bytes
510  * @param[out] port Switch port identifier
511  * @return Error code
512  **/
513 
514 error_t ksz8895UntagFrame(NetInterface *interface, uint8_t **frame,
515  size_t *length, uint8_t *port)
516 {
517 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
518  error_t error;
519  uint8_t *tailTag;
520 
521  //Valid Ethernet frame received?
522  if(*length >= (sizeof(EthHeader) + sizeof(uint8_t)))
523  {
524  //The tail tag is inserted at the end of the packet, just before the CRC
525  tailTag = *frame + *length - sizeof(uint8_t);
526 
527  //The one byte tail tagging is used to indicate the source port
528  *port = KSZ8895_TAIL_TAG_DECODE(*tailTag);
529 
530  //Strip tail tag from Ethernet frame
531  *length -= sizeof(uint8_t);
532 
533  //Successful processing
534  error = NO_ERROR;
535  }
536  else
537  {
538  //Drop the received frame
539  error = ERROR_INVALID_LENGTH;
540  }
541 
542  //Return status code
543  return error;
544 #else
545  //Tail tagging mode is not implemented
546  return NO_ERROR;
547 #endif
548 }
549 
550 
551 /**
552  * @brief Write PHY register
553  * @param[in] interface Underlying network interface
554  * @param[in] port Port number
555  * @param[in] address PHY register address
556  * @param[in] data Register value
557  **/
558 
559 void ksz8895WritePhyReg(NetInterface *interface, uint8_t port,
560  uint8_t address, uint16_t data)
561 {
562  //Write the specified PHY register
563  interface->nicDriver->writePhyReg(SMI_OPCODE_WRITE, port, address, data);
564 }
565 
566 
567 /**
568  * @brief Read PHY register
569  * @param[in] interface Underlying network interface
570  * @param[in] port Port number
571  * @param[in] address PHY register address
572  * @return Register value
573  **/
574 
575 uint16_t ksz8895ReadPhyReg(NetInterface *interface, uint8_t port,
576  uint8_t address)
577 {
578  //Read the specified PHY register
579  return interface->nicDriver->readPhyReg(SMI_OPCODE_READ, port, address);
580 }
581 
582 
583 /**
584  * @brief Dump PHY registers for debugging purpose
585  * @param[in] interface Underlying network interface
586  * @param[in] port Port number
587  **/
588 
589 void ksz8895DumpPhyReg(NetInterface *interface, uint8_t port)
590 {
591  uint8_t i;
592 
593  //Loop through PHY registers
594  for(i = 0; i < 32; i++)
595  {
596  //Display current PHY register
597  TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i,
598  ksz8895ReadPhyReg(interface, port, i));
599  }
600 
601  //Terminate with a line feed
602  TRACE_DEBUG("\r\n");
603 }
604 
605 
606 /**
607  * @brief Write switch register
608  * @param[in] interface Underlying network interface
609  * @param[in] address Switch register address
610  * @param[in] data Register value
611  **/
612 
613 void ksz8895WriteSwitchReg(NetInterface *interface, uint8_t address,
614  uint8_t data)
615 {
616  uint8_t phyAddr;
617  uint8_t regAddr;
618 
619  //SPI slave mode?
620  if(interface->spiDriver != NULL)
621  {
622  //Pull the CS pin low
623  interface->spiDriver->assertCs();
624 
625  //Set up a write operation
626  interface->spiDriver->transfer(KSZ8895_SPI_CMD_WRITE);
627  //Write register address
628  interface->spiDriver->transfer(address);
629 
630  //Write data
631  interface->spiDriver->transfer(data);
632 
633  //Terminate the operation by raising the CS pin
634  interface->spiDriver->deassertCs();
635  }
636  else
637  {
638  //SMI register write access is selected when opcode is set to 10 and
639  //bits 2:1 of the PHY address are set to 11
640  phyAddr = 0x06 | ((address >> 3) & 0x18) | ((address >> 5) & 0x01);
641 
642  //Register address field forms register address bits 4:0
643  regAddr = address & 0x1F;
644 
645  //Registers are 8 data bits wide. For write operation, data bits 15:8
646  //are not defined, and hence can be set to either zeroes or ones
647  interface->nicDriver->writePhyReg(SMI_OPCODE_WRITE, phyAddr, regAddr,
648  data);
649  }
650 }
651 
652 
653 /**
654  * @brief Read switch register
655  * @param[in] interface Underlying network interface
656  * @param[in] address Switch register address
657  * @return Register value
658  **/
659 
660 uint8_t ksz8895ReadSwitchReg(NetInterface *interface, uint8_t address)
661 {
662  uint8_t phyAddr;
663  uint8_t regAddr;
664  uint8_t data;
665 
666  //SPI slave mode?
667  if(interface->spiDriver != NULL)
668  {
669  //Pull the CS pin low
670  interface->spiDriver->assertCs();
671 
672  //Set up a read operation
673  interface->spiDriver->transfer(KSZ8895_SPI_CMD_READ);
674  //Write register address
675  interface->spiDriver->transfer(address);
676 
677  //Read data
678  data = interface->spiDriver->transfer(0xFF);
679 
680  //Terminate the operation by raising the CS pin
681  interface->spiDriver->deassertCs();
682  }
683  else
684  {
685  //SMI register read access is selected when opcode is set to 10 and
686  //bits 2:1 of the PHY address are set to 11
687  phyAddr = 0x06 | ((address >> 3) & 0x18) | ((address >> 5) & 0x01);
688 
689  //Register address field forms register address bits 4:0
690  regAddr = address & 0x1F;
691 
692  //Registers are 8 data bits wide. For read operation, data bits 15:8
693  //are read back as zeroes
694  data = interface->nicDriver->readPhyReg(SMI_OPCODE_READ, phyAddr,
695  regAddr) & 0xFF;
696  }
697 
698  //Return register value
699  return data;
700 }
701 
702 
703 /**
704  * @brief Dump switch registers for debugging purpose
705  * @param[in] interface Underlying network interface
706  **/
707 
709 {
710  uint16_t i;
711 
712  //Loop through switch registers
713  for(i = 0; i < 256; i++)
714  {
715  //Display current switch register
716  TRACE_DEBUG("0x%02" PRIX16 " (%02" PRIu16 ") : 0x%02" PRIX8 "\r\n",
717  i, i, ksz8895ReadSwitchReg(interface, i));
718  }
719 
720  //Terminate with a line feed
721  TRACE_DEBUG("\r\n");
722 }
void nicNotifyLinkChange(NetInterface *interface)
Process link state change notification.
Definition: nic.c:525
bool_t ksz8895GetLinkState(NetInterface *interface, uint8_t port)
Get link state.
KSZ8895 5-port Ethernet switch.
uint8_t length
Definition: dtls_misc.h:149
#define KSZ8895_PORTn_CTRL2(port)
int bool_t
Definition: compiler_port.h:49
const uint8_t ksz8895IngressTailTag[5]
Tail tag rules (host to KSZ8895)
#define KSZ8895_PORT1
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:119
#define KSZ8895_CHIP_ID1_START_SWITCH
#define KSZ8895_PORTn_CTRL7_STAT2(port)
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:88
#define KSZ8895_CHIP_ID1
#define TRUE
Definition: os_port.h:50
PHY driver.
Definition: nic.h:214
#define KSZ8895_PORTn_CTRL7_STAT2_OP_MODE_100BTX_FD
void ksz8895Tick(NetInterface *interface)
KSZ8895 timer handler.
#define KSZ8895_GLOBAL_CTRL10_TAIL_TAG_EN
#define NET_INTERFACE_COUNT
Definition: net.h:109
void ksz8895WriteSwitchReg(NetInterface *interface, uint8_t address, uint8_t data)
Write switch register.
#define KSZ8895_SPI_CMD_WRITE
#define KSZ8895_PORTn_CTRL7_STAT2_OP_MODE_10BT_HD
#define SMI_OPCODE_WRITE
Definition: nic.h:62
const PhyDriver ksz8895PhyDriver
KSZ8895 Ethernet switch driver.
#define KSZ8895_PORTn_CTRL2_LEARNING_DIS
void ksz8895EnableIrq(NetInterface *interface)
Enable interrupts.
#define FALSE
Definition: os_port.h:46
NetInterface netInterface[NET_INTERFACE_COUNT]
Definition: net.c:79
char_t type
error_t
Error codes.
Definition: error.h:42
#define KSZ8895_PORT4
#define KSZ8895_PORTn_STAT1(port)
#define NetInterface
Definition: net.h:36
@ NIC_LINK_SPEED_10MBPS
Definition: nic.h:105
#define KSZ8895_GLOBAL_CTRL10
@ ERROR_INVALID_LENGTH
Definition: error.h:109
void ksz8895DumpSwitchReg(NetInterface *interface)
Dump switch registers for debugging purpose.
#define KSZ8895_PORTn_STAT1_LINK_GOOD
error_t ethPadFrame(NetBuffer *buffer, size_t *length)
Ethernet frame padding.
OsMutex netMutex
Definition: net.c:75
#define KSZ8895_PORTn_CTRL7_STAT2_OP_MODE
OsEvent netEvent
Definition: net.c:77
#define SMI_OPCODE_READ
Definition: nic.h:63
error_t ksz8895UntagFrame(NetInterface *interface, uint8_t **frame, size_t *length, uint8_t *port)
Decode tail tag from incoming Ethernet frame.
#define TRACE_INFO(...)
Definition: debug.h:94
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
#define KSZ8895_PORTn_CTRL7_STAT2_OP_MODE_100BTX_HD
#define KSZ8895_TAIL_TAG_DECODE(tag)
#define KSZ8895_PORTn_CTRL2_RECEIVE_EN
uint16_t port
Definition: dns_common.h:223
#define TRACE_WARNING(...)
Definition: debug.h:84
#define KSZ8895_SPI_CMD_READ
#define TRACE_DEBUG(...)
Definition: debug.h:106
#define KSZ8895_TAIL_TAG_ENCODE(port)
uint16_t regAddr
#define KSZ8895_CHIP_ID0
error_t netBufferAppend(NetBuffer *dest, const void *src, size_t length)
Append data a multi-part buffer.
Definition: net_mem.c:586
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
#define KSZ8895_PORTn_CTRL2_TRANSMIT_EN
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
void ksz8895DisableIrq(NetInterface *interface)
Disable interrupts.
void ksz8895WritePhyReg(NetInterface *interface, uint8_t port, uint8_t address, uint16_t data)
Write PHY register.
@ NIC_HALF_DUPLEX_MODE
Definition: nic.h:118
void ksz8895EventHandler(NetInterface *interface)
KSZ8895 event handler.
@ ERROR_WRONG_IDENTIFIER
Definition: error.h:88
error_t ksz8895TagFrame(NetInterface *interface, NetBuffer *buffer, size_t *offset, uint8_t port, uint16_t *type)
Add tail tag to Ethernet frame.
#define KSZ8895_PORTn_CTRL7_STAT2_OP_MODE_10BT_FD
Ipv6Addr address
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
uint16_t ksz8895ReadPhyReg(NetInterface *interface, uint8_t port, uint8_t address)
Read PHY register.
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:106
unsigned int uint_t
Definition: compiler_port.h:45
__start_packed struct @110 EthHeader
Ethernet frame header.
TCP/IP stack core.
uint8_t data[]
Definition: dtls_misc.h:176
error_t ksz8895Init(NetInterface *interface)
KSZ8895 Ethernet switch initialization.
void ksz8895DumpPhyReg(NetInterface *interface, uint8_t port)
Dump PHY registers for debugging purpose.
#define KSZ8895_CHIP_ID0_FAMILY_ID_DEFAULT
Helper functions for Ethernet.
@ NO_ERROR
Success.
Definition: error.h:44
uint8_t ksz8895ReadSwitchReg(NetInterface *interface, uint8_t address)
Read switch register.
Debugging facilities.