dm9000_driver.c
Go to the documentation of this file.
1 /**
2  * @file dm9000_driver.c
3  * @brief DM9000A/B Ethernet controller
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.h"
38 #include "debug.h"
39 
40 
41 /**
42  * @brief DM9000 driver
43  **/
44 
46 {
48  ETH_MTU,
49  dm9000Init,
50  dm9000Tick,
56  NULL,
57  NULL,
58  NULL,
59  TRUE,
60  TRUE,
61  TRUE,
62  FALSE
63 };
64 
65 
66 /**
67  * @brief DM9000 controller initialization
68  * @param[in] interface Underlying network interface
69  * @return Error code
70  **/
71 
73 {
74  uint_t i;
75  uint16_t vendorId;
76  uint16_t productId;
77  uint8_t chipRevision;
78  Dm9000Context *context;
79 
80  //Debug message
81  TRACE_INFO("Initializing DM9000 Ethernet controller...\r\n");
82 
83  //Initialize external interrupt line
84  interface->extIntDriver->init();
85 
86  //Point to the driver context
87  context = (Dm9000Context *) interface->nicContext;
88 
89  //Initialize driver specific variables
90  context->queuedPackets = 0;
91 
92  //Allocate TX and RX buffers
95 
96  //Failed to allocate memory?
97  if(context->txBuffer == NULL || context->rxBuffer == NULL)
98  {
99  //Clean up side effects
100  memPoolFree(context->txBuffer);
101  memPoolFree(context->rxBuffer);
102 
103  //Report an error
104  return ERROR_OUT_OF_MEMORY;
105  }
106 
107  //Retrieve vendorID, product ID and chip revision
110  chipRevision = dm9000ReadReg(DM9000_REG_CHIPR);
111 
112  //Check vendor ID and product ID
113  if(vendorId != DM9000_VID || productId != DM9000_PID)
114  return ERROR_WRONG_IDENTIFIER;
115  //Check chip revision
116  if(chipRevision != DM9000A_CHIP_REV && chipRevision != DM9000B_CHIP_REV)
117  return ERROR_WRONG_IDENTIFIER;
118 
119  //Power up the internal PHY by clearing PHYPD
121  //Wait for the PHY to be ready
122  sleep(10);
123 
124  //Software reset
126  //Wait for the reset to complete
128 
129  //PHY software reset
131  //Wait for the PHY reset to complete
133 
134  //Debug message
135  TRACE_INFO(" VID = 0x%04" PRIX16 "\r\n", vendorId);
136  TRACE_INFO(" PID = 0x%04" PRIX16 "\r\n", productId);
137  TRACE_INFO(" CHIPR = 0x%02" PRIX8 "\r\n", chipRevision);
138  TRACE_INFO(" PHYIDR1 = 0x%04" PRIX16 "\r\n", dm9000ReadPhyReg(DM9000_PHY_REG_PHYIDR1));
139  TRACE_INFO(" PHYIDR2 = 0x%04" PRIX16 "\r\n", dm9000ReadPhyReg(DM9000_PHY_REG_PHYIDR2));
140 
141  //Enable loopback mode?
142 #if (DM9000_LOOPBACK_MODE == ENABLED)
145 #endif
146 
147  //Set host MAC address
148  for(i = 0; i < 6; i++)
149  dm9000WriteReg(DM9000_REG_PAR0 + i, interface->macAddr.b[i]);
150 
151  //Initialize hash table
152  for(i = 0; i < 8; i++)
153  dm9000WriteReg(DM9000_REG_MAR0 + i, 0x00);
154 
155  //Always accept broadcast packets
157 
158  //Enable the Pointer Auto Return function
160  //Clear NSR status bits
162  //Clear interrupt flags
164  //Enable interrupts
166  //Enable the receiver by setting RXEN
168 
169  //Accept any packets from the upper layer
170  osSetEvent(&interface->nicTxEvent);
171 
172  //Force the TCP/IP stack to poll the link state at startup
173  interface->nicEvent = TRUE;
174  //Notify the TCP/IP stack of the event
176 
177  //Successful initialization
178  return NO_ERROR;
179 }
180 
181 
182 /**
183  * @brief DM9000 timer handler
184  * @param[in] interface Underlying network interface
185  **/
186 
187 void dm9000Tick(NetInterface *interface)
188 {
189 }
190 
191 
192 /**
193  * @brief Enable interrupts
194  * @param[in] interface Underlying network interface
195  **/
196 
198 {
199  //Enable interrupts
200  interface->extIntDriver->enableIrq();
201 }
202 
203 
204 /**
205  * @brief Disable interrupts
206  * @param[in] interface Underlying network interface
207  **/
208 
210 {
211  //Disable interrupts
212  interface->extIntDriver->disableIrq();
213 }
214 
215 
216 /**
217  * @brief DM9000 interrupt service routine
218  * @param[in] interface Underlying network interface
219  * @return TRUE if a higher priority task must be woken. Else FALSE is returned
220  **/
221 
223 {
224  bool_t flag;
225  uint8_t status;
226  uint8_t mask;
227  Dm9000Context *context;
228 
229  //This flag will be set if a higher priority task must be woken
230  flag = FALSE;
231 
232  //Point to the driver context
233  context = (Dm9000Context *) interface->nicContext;
234 
235  //Read interrupt status register
236  status = dm9000ReadReg(DM9000_REG_ISR);
237 
238  //Link status change?
239  if(status & ISR_LNKCHG)
240  {
241  //Read interrupt mask register
243  //Disable LNKCHGI interrupt
245 
246  //Set event flag
247  interface->nicEvent = TRUE;
248  //Notify the TCP/IP stack of the event
249  flag |= osSetEventFromIsr(&netEvent);
250  }
251 
252  //Packet transmission complete?
253  if(status & ISR_PT)
254  {
255  //Check TX complete status bits
257  {
258  //The transmission of the current packet is complete
259  if(context->queuedPackets > 0)
260  context->queuedPackets--;
261 
262  //Notify the TCP/IP stack that the transmitter is ready to send
263  flag |= osSetEventFromIsr(&interface->nicTxEvent);
264  }
265 
266  //Clear interrupt flag
268  }
269 
270  //Packet received?
271  if(status & ISR_PR)
272  {
273  //Read interrupt mask register
275  //Disable PRI interrupt
277 
278  //Set event flag
279  interface->nicEvent = TRUE;
280  //Notify the TCP/IP stack of the event
281  flag |= osSetEventFromIsr(&netEvent);
282  }
283 
284  //A higher priority task must be woken?
285  return flag;
286 }
287 
288 
289 /**
290  * @brief DM9000 event handler
291  * @param[in] interface Underlying network interface
292  **/
293 
295 {
296  error_t error;
297  uint8_t status;
298 
299  //Read interrupt status register
300  status = dm9000ReadReg(DM9000_REG_ISR);
301 
302  //Check whether the link status has changed?
303  if(status & ISR_LNKCHG)
304  {
305  //Clear interrupt flag
307  //Read network status register
308  status = dm9000ReadReg(DM9000_REG_NSR);
309 
310  //Check link state
311  if(status & NSR_LINKST)
312  {
313  //Get current speed
314  if(status & NSR_SPEED)
315  interface->linkSpeed = NIC_LINK_SPEED_10MBPS;
316  else
317  interface->linkSpeed = NIC_LINK_SPEED_100MBPS;
318 
319  //Read network control register
320  status = dm9000ReadReg(DM9000_REG_NCR);
321 
322  //Determine the new duplex mode
323  if(status & NCR_FDX)
324  interface->duplexMode = NIC_FULL_DUPLEX_MODE;
325  else
326  interface->duplexMode = NIC_HALF_DUPLEX_MODE;
327 
328  //Link is up
329  interface->linkState = TRUE;
330  }
331  else
332  {
333  //Link is down
334  interface->linkState = FALSE;
335  }
336 
337  //Process link state change event
338  nicNotifyLinkChange(interface);
339  }
340 
341  //Check whether a packet has been received?
342  if(status & ISR_PR)
343  {
344  //Clear interrupt flag
346 
347  //Process all pending packets
348  do
349  {
350  //Read incoming packet
351  error = dm9000ReceivePacket(interface);
352 
353  //No more data in the receive buffer?
354  } while(error != ERROR_BUFFER_EMPTY);
355  }
356 
357  //Re-enable LNKCHGI and PRI interrupts
359 }
360 
361 
362 /**
363  * @brief Send a packet to DM9000
364  * @param[in] interface Underlying network interface
365  * @param[in] buffer Multi-part buffer containing the data to send
366  * @param[in] offset Offset to the first data byte
367  * @return Error code
368  **/
369 
371  const NetBuffer *buffer, size_t offset)
372 {
373  size_t i;
374  size_t length;
375  uint16_t *p;
376  Dm9000Context *context;
377 
378  //Point to the driver context
379  context = (Dm9000Context *) interface->nicContext;
380 
381  //Retrieve the length of the packet
382  length = netBufferGetLength(buffer) - offset;
383 
384  //Check the frame length
386  {
387  //The transmitter can accept another packet
388  osSetEvent(&interface->nicTxEvent);
389  //Report an error
390  return ERROR_INVALID_LENGTH;
391  }
392 
393  //Copy user data
394  netBufferRead(context->txBuffer, buffer, offset, length);
395 
396  //A dummy write is required before accessing FIFO
398  //Select MWCMD register
400 
401  //Point to the beginning of the buffer
402  p = (uint16_t *) context->txBuffer;
403 
404  //Write data to the FIFO using 16-bit mode
405  for(i = length; i > 1; i -= 2)
406  DM9000_DATA_REG = *(p++);
407 
408  //Odd number of bytes?
409  if(i > 0)
410  DM9000_DATA_REG = *((uint8_t *) p);
411 
412  //Write the number of bytes to send
415 
416  //Clear interrupt flag
418  //Start data transfer
420 
421  //The packet was successfully written to FIFO
422  context->queuedPackets++;
423 
424  //Successful processing
425  return NO_ERROR;
426 }
427 
428 
429 /**
430  * @brief Receive a packet
431  * @param[in] interface Underlying network interface
432  * @return Error code
433  **/
434 
436 {
437  error_t error;
438  size_t i;
439  size_t n;
440  size_t length;
441  volatile uint8_t status;
442  volatile uint16_t data;
443  Dm9000Context *context;
444 
445  //Point to the driver context
446  context = (Dm9000Context *) interface->nicContext;
447 
448  //A dummy read is required before accessing the 4-byte header
450 
451  //Select MRCMDX1 register
453  //Read the first byte of the header
454  status = LSB(DM9000_DATA_REG);
455 
456  //The first byte indicates if a packet has been received
457  if(status == 0x01)
458  {
459  //Select MRCMD register
461  //The second byte is the RX status byte
462  status = MSB(DM9000_DATA_REG);
463 
464  //Retrieve packet length
466  //Limit the number of data to read
468 
469  //Point to the beginning of the buffer
470  i = 0;
471 
472  //Make sure no error occurred
473  if(!(status & (RSR_LCS | RSR_RWTO | RSR_PLE | RSR_AE | RSR_CE | RSR_FOE)))
474  {
475  //Read data from FIFO using 16-bit mode
476  while((i + 1) < n)
477  {
479  context->rxBuffer[i++] = LSB(data);
480  context->rxBuffer[i++] = MSB(data);
481  }
482 
483  //Odd number of bytes to read?
484  if((i + 1) == n)
485  {
487  context->rxBuffer[i] = LSB(data);
488  i += 2;
489  }
490 
491  //Valid packet received
492  error = NO_ERROR;
493  }
494  else
495  {
496  //The received packet contains an error
497  error = ERROR_INVALID_PACKET;
498  }
499 
500  //Flush remaining bytes
501  while(i < length)
502  {
504  i += 2;
505  }
506  }
507  else
508  {
509  //No more data in the receive buffer
510  error = ERROR_BUFFER_EMPTY;
511  }
512 
513  //Check whether a valid packet has been received
514  if(!error)
515  {
516  //Pass the packet to the upper layer
517  nicProcessPacket(interface, context->rxBuffer, n);
518  }
519 
520  //Return status code
521  return error;
522 }
523 
524 
525 /**
526  * @brief Configure MAC address filtering
527  * @param[in] interface Underlying network interface
528  * @return Error code
529  **/
530 
532 {
533  uint_t i;
534  uint_t k;
535  uint32_t crc;
536  uint8_t hashTable[8];
537  MacFilterEntry *entry;
538 
539  //Debug message
540  TRACE_DEBUG("Updating MAC filter...\r\n");
541 
542  //Clear hash table
543  memset(hashTable, 0, sizeof(hashTable));
544  //Always accept broadcast packets regardless of the MAC filter table
545  hashTable[7] = 0x80;
546 
547  //The MAC address filter contains the list of MAC addresses to accept
548  //when receiving an Ethernet frame
549  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
550  {
551  //Point to the current entry
552  entry = &interface->macAddrFilter[i];
553 
554  //Valid entry?
555  if(entry->refCount > 0)
556  {
557  //Compute CRC over the current MAC address
558  crc = dm9000CalcCrc(&entry->addr, sizeof(MacAddr));
559  //Calculate the corresponding index in the table
560  k = crc & 0x3F;
561  //Update hash table contents
562  hashTable[k / 8] |= (1 << (k % 8));
563  }
564  }
565 
566  //Write the hash table to the DM9000 controller
567  for(i = 0; i < 8; i++)
568  dm9000WriteReg(DM9000_REG_MAR0 + i, hashTable[i]);
569 
570  //Debug message
571  TRACE_DEBUG(" MAR = %02" PRIX8 " %02" PRIX8 " %02" PRIX8 " %02" PRIX8 " "
572  "%02" PRIX8 " %02" PRIX8 " %02" PRIX8 " %02" PRIX8 "\r\n",
577 
578  //Successful processing
579  return NO_ERROR;
580 }
581 
582 
583 /**
584  * @brief Write DM9000 register
585  * @param[in] address Register address
586  * @param[in] data Register value
587  **/
588 
589 void dm9000WriteReg(uint8_t address, uint8_t data)
590 {
591  //Write register address to INDEX register
593  //Write register value to DATA register
595 }
596 
597 
598 /**
599  * @brief Read DM9000 register
600  * @param[in] address Register address
601  * @return Register value
602  **/
603 
604 uint8_t dm9000ReadReg(uint8_t address)
605 {
606  //Write register address to INDEX register
608  //Read register value from DATA register
609  return DM9000_DATA_REG;
610 }
611 
612 
613 /**
614  * @brief Write DM9000 PHY register
615  * @param[in] address PHY register address
616  * @param[in] data Register value
617  **/
618 
619 void dm9000WritePhyReg(uint8_t address, uint16_t data)
620 {
621  //Write PHY register address
623  //Write register value
626 
627  //Start the write operation
629  //PHY access is still in progress?
631 
632  //Wait 5us minimum
633  usleep(5);
634  //Clear command register
636 }
637 
638 
639 /**
640  * @brief Read DM9000 PHY register
641  * @param[in] address PHY register address
642  * @return Register value
643  **/
644 
645 uint16_t dm9000ReadPhyReg(uint8_t address)
646 {
647  //Write PHY register address
649 
650  //Start the read operation
652  //PHY access is still in progress?
654 
655  //Clear command register
657  //Wait 5us minimum
658  usleep(5);
659 
660  //Return register value
662 }
663 
664 
665 /**
666  * @brief CRC calculation
667  * @param[in] data Pointer to the data over which to calculate the CRC
668  * @param[in] length Number of bytes to process
669  * @return Resulting CRC value
670  **/
671 
672 uint32_t dm9000CalcCrc(const void *data, size_t length)
673 {
674  uint_t i;
675  uint_t j;
676 
677  //Point to the data over which to calculate the CRC
678  const uint8_t *p = (uint8_t *) data;
679  //CRC preset value
680  uint32_t crc = 0xFFFFFFFF;
681 
682  //Loop through data
683  for(i = 0; i < length; i++)
684  {
685  //Update CRC value
686  crc ^= p[i];
687  //The message is processed bit by bit
688  for(j = 0; j < 8; j++)
689  {
690  if(crc & 0x00000001)
691  crc = (crc >> 1) ^ 0xEDB88320;
692  else
693  crc = crc >> 1;
694  }
695  }
696 
697  //Return CRC value
698  return crc;
699 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
void nicNotifyLinkChange(NetInterface *interface)
Process link state change notification.
Definition: nic.c:525
void dm9000WritePhyReg(uint8_t address, uint16_t data)
Write DM9000 PHY register.
error_t dm9000UpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
#define usleep(delay)
Definition: os_port.h:127
uint8_t length
Definition: dtls_misc.h:149
#define DM9000_REG_IMR
int bool_t
Definition: compiler_port.h:49
#define DM9000B_CHIP_REV
Definition: dm9000_driver.h:66
#define RSR_AE
#define NSR_LINKST
#define DM9000_INDEX_REG
Definition: dm9000_driver.h:46
void dm9000WriteReg(uint8_t address, uint8_t data)
Write DM9000 register.
void memPoolFree(void *p)
Release a memory block.
Definition: net_mem.c:166
uint8_t * rxBuffer
Receive buffer.
size_t netBufferRead(void *dest, const NetBuffer *src, size_t srcOffset, size_t length)
Read data from a multi-part buffer.
Definition: net_mem.c:672
#define DM9000_REG_MAR0
Definition: dm9000_driver.h:91
#define DM9000_REG_MAR4
Definition: dm9000_driver.h:95
uint8_t p
Definition: ndp.h:298
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length)
Handle a packet received by the network controller.
Definition: nic.c:383
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:88
#define RSR_RWTO
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:74
#define TRUE
Definition: os_port.h:50
#define sleep(delay)
Definition: os_port.h:131
#define ETH_MAX_FRAME_SIZE
Definition: ethernet.h:89
#define DM9000_VID
Definition: dm9000_driver.h:63
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:223
#define BMCR_SPEED_SEL
#define DM9000_REG_PAR0
Definition: dm9000_driver.h:85
#define RCR_RXEN
#define RCR_DIS_CRC
#define DM9000_REG_MAR2
Definition: dm9000_driver.h:93
void * memPoolAlloc(size_t size)
Allocate a memory block.
Definition: net_mem.c:100
void dm9000Tick(NetInterface *interface)
DM9000 timer handler.
#define DM9000_LBK_PHY
#define RSR_LCS
#define RSR_CE
#define DM9000_REG_VIDL
#define NSR_TX2END
#define DM9000_REG_NSR
Definition: dm9000_driver.h:70
#define ISR_LNKCHG
#define NSR_WAKEST
#define RCR_DIS_LONG
Ethernet.
uint32_t dm9000CalcCrc(const void *data, size_t length)
CRC calculation.
error_t dm9000Init(NetInterface *interface)
DM9000 controller initialization.
Definition: dm9000_driver.c:72
#define EPCR_ERPRW
#define ISR_ROO
#define DM9000_REG_RCR
Definition: dm9000_driver.h:74
#define DM9000_REG_MAR6
Definition: dm9000_driver.h:97
#define RSR_FOE
#define FALSE
Definition: os_port.h:46
#define DM9000_REG_PIDH
#define BMCR_DUPLEX_MODE
#define DM9000_REG_MRCMDX1
#define ISR_UDRUN
error_t
Error codes.
Definition: error.h:42
error_t dm9000ReceivePacket(NetInterface *interface)
Receive a packet.
#define DM9000_DATA_REG
Definition: dm9000_driver.h:51
#define NSR_TX1END
#define EPCR_EPOS
uint16_t dm9000ReadPhyReg(uint8_t address)
Read DM9000 PHY register.
#define IMR_PAR
#define NetInterface
Definition: net.h:36
MacAddr addr
MAC address.
Definition: ethernet.h:222
#define DM9000_REG_TXPLH
#define NCR_RST
uint8_t mask
Definition: web_socket.h:317
OsEvent netEvent
Definition: net.c:77
#define MSB(x)
Definition: os_port.h:58
#define DM9000_REG_GPR
#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 LSB(x)
Definition: os_port.h:54
#define DM9000_REG_TXPLL
#define DM9000_REG_EPCR
Definition: dm9000_driver.h:80
#define DM9000_REG_ISR
#define NSR_SPEED
#define MIN(a, b)
Definition: os_port.h:62
#define IMR_PRI
#define DM9000_REG_EPAR
Definition: dm9000_driver.h:81
#define EPCR_ERPRR
#define DM9000_REG_MWCMD
#define DM9000_REG_MRCMDX
#define DM9000_REG_EPDRH
Definition: dm9000_driver.h:83
uint8_t dm9000ReadReg(uint8_t address)
Read DM9000 register.
#define NCR_FDX
#define DM9000A_CHIP_REV
Definition: dm9000_driver.h:65
#define TRACE_DEBUG(...)
Definition: debug.h:106
#define DM9000_REG_CHIPR
#define DM9000_REG_MAR1
Definition: dm9000_driver.h:92
#define DM9000_REG_MWCMDX
#define IMR_LNKCHGI
#define ETH_MTU
Definition: ethernet.h:91
#define DM9000_REG_MAR3
Definition: dm9000_driver.h:94
uint8_t n
MAC filter table entry.
Definition: ethernet.h:220
#define DM9000_PHY_REG_PHYIDR1
void dm9000DisableIrq(NetInterface *interface)
Disable interrupts.
#define BMCR_LOOPBACK
uint8_t * txBuffer
Transmit buffer.
#define DM9000_REG_TCR
Definition: dm9000_driver.h:71
DM9000A/B Ethernet controller.
#define BMCR_RST
void dm9000EventHandler(NetInterface *interface)
DM9000 event handler.
error_t dm9000SendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset)
Send a packet to DM9000.
#define DM9000_REG_EPDRL
Definition: dm9000_driver.h:82
#define DM9000_REG_MAR5
Definition: dm9000_driver.h:96
Ipv6Addr address
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
bool_t dm9000IrqHandler(NetInterface *interface)
DM9000 interrupt service routine.
#define IMR_PTI
#define DM9000_REG_VIDH
#define ISR_PR
DM9000 driver context.
#define DM9000_PHY_REG_PHYIDR2
#define TCR_TXREQ
#define DM9000_PID
Definition: dm9000_driver.h:64
#define DM9000_REG_PIDL
#define ISR_ROS
unsigned int uint_t
Definition: compiler_port.h:45
TCP/IP stack core.
uint8_t data[]
Definition: dtls_misc.h:176
#define DM9000_PHY_REG_BMCR
NIC driver.
Definition: nic.h:179
#define DM9000_REG_MAR7
Definition: dm9000_driver.h:98
#define BMCR_AN_EN
#define EPCR_ERRE
#define RSR_PLE
#define DM9000_REG_NCR
Definition: dm9000_driver.h:69
const NicDriver dm9000Driver
DM9000 driver.
Definition: dm9000_driver.c:45
uint_t queuedPackets
Number of packets in transmission buffer.
void dm9000EnableIrq(NetInterface *interface)
Enable interrupts.
#define ISR_PT
Success.
Definition: error.h:44
Debugging facilities.
__start_packed struct @108 MacAddr
MAC address.
#define DM9000_REG_MRCMD
Ethernet interface.
Definition: nic.h:79