Merge remote-tracking branch 'refs/remotes/Smoothieware/edge' into fix/http_upload
[clinton/Smoothieware.git] / src / libs / Network / Drivers / LPC17XX_Ethernet.cpp
CommitLineData
d4ee6ee2 1#if 1
618e6b09
MM
2#include "LPC17XX_Ethernet.h"
3
d4ee6ee2
JM
4#include "Kernel.h"
5
618e6b09
MM
6#include <cstring>
7#include <cstdio>
8
9#include "lpc17xx_clkpwr.h"
10
11#include <mri.h>
12
13// #include "netcore.h"
14
d5c2e71c
JM
15#define DEBUG_PRINTF printf
16
618e6b09
MM
17static const uint8_t EMAC_clkdiv[] = { 4, 6, 8, 10, 14, 20, 28 };
18
19/*--------------------------- write_PHY -------------------------------------*/
20/*********************************************************************//**
21* @brief Write value to PHY device
22* @param[in] PhyReg: PHY Register address
23* @param[in] Value: Value to write
24* @return 0 - if success
25* 1 - if fail
26***********************************************************************/
27static int32_t write_PHY (uint32_t PhyReg, uint16_t Value)
28{
29 /* Write a data 'Value' to PHY register 'PhyReg'. */
30 uint32_t tout;
31
32 LPC_EMAC->MADR = EMAC_DEF_ADR | PhyReg;
33 LPC_EMAC->MWTD = Value;
34
35 /* Wait until operation completed */
36 tout = 0;
37 for (tout = 0; tout < EMAC_MII_WR_TOUT; tout++) {
38 if ((LPC_EMAC->MIND & EMAC_MIND_BUSY) == 0) {
39 return (0);
40 }
41 }
d5c2e71c 42 DEBUG_PRINTF("write PHY %lu %04X failed!\n", PhyReg, Value);
618e6b09
MM
43 // Time out!
44 return (-1);
45}
46
47
48/*--------------------------- read_PHY --------------------------------------*/
49/*********************************************************************//**
50* @brief Read value from PHY device
51* @param[in] PhyReg: PHY Register address
52* @return 0 - if success
53* 1 - if fail
54***********************************************************************/
55static int32_t read_PHY (uint32_t PhyReg)
56{
57 /* Read a PHY register 'PhyReg'. */
58 uint32_t tout;
59
60 LPC_EMAC->MADR = EMAC_DEF_ADR | PhyReg;
61 LPC_EMAC->MCMD = EMAC_MCMD_READ;
62
63 /* Wait until operation completed */
64 tout = 0;
65 for (tout = 0; tout < EMAC_MII_RD_TOUT; tout++) {
66 if ((LPC_EMAC->MIND & EMAC_MIND_BUSY) == 0) {
67 LPC_EMAC->MCMD = 0;
68 return (LPC_EMAC->MRDD);
69 }
70 }
d5c2e71c 71 DEBUG_PRINTF("read PHY %lu failed!\n", PhyReg);
618e6b09
MM
72 // Time out!
73 return (-1);
74}
75
76/*********************************************************************//**
77* @brief Set Station MAC address for EMAC module
78* @param[in] abStationAddr Pointer to Station address that contains 6-bytes
79* of MAC address (should be in order from MAC Address 1 to MAC Address 6)
80* @return None
81**********************************************************************/
82static void setEmacAddr(uint8_t abStationAddr[])
83{
84 /* Set the Ethernet MAC Address registers */
85 LPC_EMAC->SA0 = ((uint32_t)abStationAddr[5] << 8) | (uint32_t)abStationAddr[4];
86 LPC_EMAC->SA1 = ((uint32_t)abStationAddr[3] << 8) | (uint32_t)abStationAddr[2];
87 LPC_EMAC->SA2 = ((uint32_t)abStationAddr[1] << 8) | (uint32_t)abStationAddr[0];
88}
89
90/*********************************************************************//**
91* @brief Set specified PHY mode in EMAC peripheral
92* @param[in] ulPHYMode Specified PHY mode, should be:
93* - EMAC_MODE_AUTO
94* - EMAC_MODE_10M_FULL
95* - EMAC_MODE_10M_HALF
96* - EMAC_MODE_100M_FULL
97* - EMAC_MODE_100M_HALF
98* @return Return (0) if no error, otherwise return (-1)
99**********************************************************************/
100int32_t emac_SetPHYMode(uint32_t ulPHYMode)
101{
102 int32_t id1, id2, tout, regv;
103
104 id1 = read_PHY (EMAC_PHY_REG_IDR1);
105 id2 = read_PHY (EMAC_PHY_REG_IDR2);
106
107 if (((id1 << 16) | (id2 & 0xFFF0)) == EMAC_SMSC_8720A) {
108 switch(ulPHYMode){
109 case EMAC_MODE_AUTO:
110 write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_AUTO_NEG);
111 /* Wait to complete Auto_Negotiation */
112 for (tout = EMAC_PHY_RESP_TOUT; tout; tout--) {
113 regv = read_PHY (EMAC_PHY_REG_BMSR);
114 if (regv & EMAC_PHY_BMSR_AUTO_DONE) {
115 /* Auto-negotiation Complete. */
116 break;
117 }
118 if (tout == 0){
119 // Time out, return error
120 return (-1);
121 }
122 }
123 break;
124 case EMAC_MODE_10M_FULL:
125 /* Connect at 10MBit full-duplex */
126 write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_FULLD_10M);
127 break;
128 case EMAC_MODE_10M_HALF:
129 /* Connect at 10MBit half-duplex */
130 write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_HALFD_10M);
131 break;
132 case EMAC_MODE_100M_FULL:
133 /* Connect at 100MBit full-duplex */
134 write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_FULLD_100M);
135 break;
136 case EMAC_MODE_100M_HALF:
137 /* Connect at 100MBit half-duplex */
138 write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_HALFD_100M);
139 break;
140 default:
141 // un-supported
142 return (-1);
143 }
144 }
145 // It's not correct module ID
146 else {
d5c2e71c 147 DEBUG_PRINTF("PHY reports id %04lX %04lX - not an SMSC 8720A\n", id1, id2);
618e6b09
MM
148 return (-1);
149 }
150
151 // Update EMAC configuration with current PHY status
152 if (EMAC_UpdatePHYStatus() < 0){
153 return (-1);
154 }
155
156 // Complete
157 return (0);
158}
159
d4ee6ee2
JM
160_rxbuf_t LPC17XX_Ethernet::rxbuf __attribute__ ((section ("AHBSRAM1"))) __attribute__((aligned(8)));
161_txbuf_t LPC17XX_Ethernet::txbuf __attribute__ ((section ("AHBSRAM1"))) __attribute__((aligned(8)));
618e6b09
MM
162
163LPC17XX_Ethernet* LPC17XX_Ethernet::instance;
164
165LPC17XX_Ethernet::LPC17XX_Ethernet()
166{
d4ee6ee2
JM
167 // TODO these need to be configurable
168 // mac_address[0] = 0xAE;
169 // mac_address[1] = 0xF0;
170 // mac_address[2] = 0x28;
171 // mac_address[3] = 0x5D;
172 // mac_address[4] = 0x66;
173 // mac_address[5] = 0x41;
174
175 // ip_address = IPA(192,168,3,222);
176 // ip_mask = 0xFFFFFF00;
177
178 for (int i = 0; i < LPC17XX_RXBUFS; i++) {
618e6b09 179 rxbuf.rxdesc[i].packet = rxbuf.buf[i];
d4ee6ee2 180 rxbuf.rxdesc[i].control = (LPC17XX_MAX_PACKET - 1) | EMAC_RCTRL_INT;
618e6b09
MM
181
182 rxbuf.rxstat[i].Info = 0;
183 rxbuf.rxstat[i].HashCRC = 0;
d4ee6ee2 184 }
618e6b09 185
d4ee6ee2 186 for (int i = 0; i < LPC17XX_TXBUFS; i++) {
618e6b09 187 txbuf.txdesc[i].packet = txbuf.buf[i];
d4ee6ee2 188 txbuf.txdesc[i].control = (LPC17XX_MAX_PACKET - 1) | EMAC_TCTRL_PAD | EMAC_TCTRL_CRC | EMAC_TCTRL_LAST | EMAC_TCTRL_INT;
618e6b09
MM
189
190 txbuf.txstat[i].Info = 0;
191 }
192
193 interface_name = (uint8_t*) malloc(5);
194 memcpy(interface_name, "eth0", 5);
195
196 instance = this;
197
198 up = false;
199}
200
201void LPC17XX_Ethernet::on_module_loaded()
202{
27e110f0
PJ
203 LPC_PINCON->PINSEL2 |= (1 << 0) | (1 << 2) | (1 << 8) | (1 << 16) | (1 << 18) | (1 << 20) | (1 << 28) | (1 << 30);
204 LPC_PINCON->PINSEL2 &= ~((1 << 1) | (1 << 3) | (1 << 9) | (1 << 17) | (1 << 19) | (1 << 21) | (1 << 29) | (1 << 31));
205 LPC_PINCON->PINSEL3 |= (1 << 0) | (1 << 2);
206 LPC_PINCON->PINSEL3 &= ~((1 << 1) | (1 << 3));
618e6b09 207
d5c2e71c 208 DEBUG_PRINTF("EMAC_INIT\n");
618e6b09 209 emac_init();
d5c2e71c 210 DEBUG_PRINTF("INIT OK\n");
618e6b09 211
d4ee6ee2 212 //register_for_event(ON_IDLE);
618e6b09
MM
213 register_for_event(ON_SECOND_TICK);
214}
215
216void LPC17XX_Ethernet::on_idle(void*)
217{
d4ee6ee2
JM
218 //_receive_frame();
219}
220
221void LPC17XX_Ethernet::on_second_tick(void *) {
222 check_interface();
618e6b09
MM
223}
224
d4ee6ee2 225void LPC17XX_Ethernet::check_interface()
618e6b09
MM
226{
227// LPC_EMAC->Command = 0x303;
228// setEmacAddr(mac_address);
d4ee6ee2 229
618e6b09
MM
230 uint32_t st;
231 st = read_PHY (EMAC_PHY_REG_BMSR);
232
233 if ((st & EMAC_PHY_BMSR_LINK_ESTABLISHED) && (st & EMAC_PHY_BMSR_AUTO_DONE) && (up == false))
234 {
235 // TODO: link up event
236 up = true;
237// net->set_interface_status(this, up);
238 uint32_t scsr = read_PHY(EMAC_PHY_REG_SCSR);
d5c2e71c 239 DEBUG_PRINTF("%s: link up: ", interface_name);
618e6b09
MM
240 switch ((scsr >> 2) & 0x7)
241 {
242 case 1:
d5c2e71c 243 DEBUG_PRINTF("10MBit Half Duplex\n");
618e6b09
MM
244 break;
245 case 5:
d5c2e71c 246 DEBUG_PRINTF("10MBit Full Duplex\n");
618e6b09
MM
247 break;
248 case 2:
d5c2e71c 249 DEBUG_PRINTF("100MBit Half Duplex\n");
618e6b09
MM
250 break;
251 case 6:
d5c2e71c 252 DEBUG_PRINTF("100MBit Full Duplex\n");
618e6b09
MM
253 break;
254 default:
d5c2e71c 255 DEBUG_PRINTF("Unknown speed: SCSR = 0x%04lX\n", scsr);
618e6b09
MM
256 break;
257 }
d5c2e71c 258 DEBUG_PRINTF("MAC Address: %02lX:%02lX:%02lX:%02lX:%02lX:%02lX\n", (LPC_EMAC->SA2) & 0xFF, (LPC_EMAC->SA2 >> 8) & 0xFF, (LPC_EMAC->SA1) & 0xFF, (LPC_EMAC->SA1 >> 8) & 0xFF, (LPC_EMAC->SA0) & 0xFF, (LPC_EMAC->SA0 >> 8) & 0xFF);
618e6b09
MM
259 }
260 else if (((st & EMAC_PHY_BMSR_LINK_ESTABLISHED) == 0) && up)
261 {
262 // TODO: link down event
263 up = false;
264// net->set_interface_status(this, up);
d5c2e71c 265 DEBUG_PRINTF("%s: link down\n", interface_name);
618e6b09
MM
266 }
267
d5c2e71c
JM
268 //DEBUG_PRINTF("PHY: id:%04lX %04lX st:%04lX\n", id1, id2, st);
269 // DEBUG_PRINTF("ETH: Rx:%lu/%lu Tx:%lu/%lu\n", LPC_EMAC->RxConsumeIndex, LPC_EMAC->RxProduceIndex, LPC_EMAC->TxProduceIndex, LPC_EMAC->TxConsumeIndex);
270 // DEBUG_PRINTF("MII: 0x%1lX\n", LPC_EMAC->MIND);
271 // DEBUG_PRINTF("Command: 0x%03lX Status: 0x%1lX\n", LPC_EMAC->Command, LPC_EMAC->Status);
272 // DEBUG_PRINTF("RxN: %lu TxN: %lu\n", LPC_EMAC->RxDescriptorNumber, LPC_EMAC->TxDescriptorNumber);
273 // DEBUG_PRINTF("MAC1: 0x%04lX MAC2: 0x%04lX\n", LPC_EMAC->MAC1, LPC_EMAC->MAC2);
274 // DEBUG_PRINTF("MAC Address: %02lX:%02lX:%02lX:%02lX:%02lX:%02lX\n", (LPC_EMAC->SA2) & 0xFF, (LPC_EMAC->SA2 >> 8) & 0xFF, (LPC_EMAC->SA1) & 0xFF, (LPC_EMAC->SA1 >> 8) & 0xFF, (LPC_EMAC->SA0) & 0xFF, (LPC_EMAC->SA0 >> 8) & 0xFF);
618e6b09
MM
275}
276
277void LPC17XX_Ethernet::emac_init()
278{
279 /* Initialize the EMAC Ethernet controller. */
280 int32_t regv,tout, tmp;
281 volatile uint32_t d;
282
283 /* Set up clock and power for Ethernet module */
284 CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCENET, ENABLE);
285
286 /* Reset all EMAC internal modules */
287 LPC_EMAC->MAC1 = EMAC_MAC1_RES_TX | EMAC_MAC1_RES_MCS_TX | EMAC_MAC1_RES_RX |
288 EMAC_MAC1_RES_MCS_RX | EMAC_MAC1_SIM_RES | EMAC_MAC1_SOFT_RES;
289
290 LPC_EMAC->Command = EMAC_CR_REG_RES | EMAC_CR_TX_RES | EMAC_CR_RX_RES;
291
292 /* A short delay after reset. */
293 for (d = 256; d; d--);
294
295 /* Initialize MAC control registers. */
296 LPC_EMAC->MAC1 = EMAC_MAC1_PASS_ALL;
297 LPC_EMAC->MAC2 = EMAC_MAC2_CRC_EN | EMAC_MAC2_PAD_EN | EMAC_MAC2_FULL_DUP;
298 LPC_EMAC->MAXF = EMAC_ETH_MAX_FLEN;
299 /*
300 * Find the clock that close to desired target clock
301 */
302 tmp = SystemCoreClock / EMAC_MCFG_MII_MAXCLK;
303 for (tout = 0; tout < (int32_t) sizeof (EMAC_clkdiv); tout++){
304 if (EMAC_clkdiv[tout] >= tmp) break;
305 }
306 tout++;
307 // Write to MAC configuration register and reset
308 LPC_EMAC->MCFG = EMAC_MCFG_CLK_SEL(tout) | EMAC_MCFG_RES_MII;
309 // release reset
310 LPC_EMAC->MCFG &= ~(EMAC_MCFG_RES_MII);
311 LPC_EMAC->CLRT = EMAC_CLRT_DEF;
312 LPC_EMAC->IPGR = EMAC_IPGR_P2_DEF;
313
314 /* Enable Reduced MII interface. */
315 LPC_EMAC->Command = EMAC_CR_RMII;
316
317 /* Reset Reduced MII Logic. */
318 LPC_EMAC->SUPP = EMAC_SUPP_RES_RMII;
319
320 for (d = 256; d; d--);
321 LPC_EMAC->SUPP = EMAC_SUPP_SPEED;
322
323 /* Put the DP83848C in reset mode */
324 write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_BMCR_RESET);
325
326 /* Wait for hardware reset to end. */
327 for (tout = EMAC_PHY_RESP_TOUT; tout; tout--) {
328 regv = read_PHY (EMAC_PHY_REG_BMCR);
329 if (!(regv & (EMAC_PHY_BMCR_RESET | EMAC_PHY_BMCR_POWERDOWN))) {
330 /* Reset complete, device not Power Down. */
331 break;
332 }
333 if (tout == 0){
334 // Time out, return ERROR
d5c2e71c 335 DEBUG_PRINTF("ETH: PHY TIMEOUT\n");
618e6b09
MM
336 return;
337 }
338 }
339
340 // Set PHY mode
341// if (emac_SetPHYMode(EMAC_MODE_AUTO) < 0){
d5c2e71c 342// DEBUG_PRINTF("ETH: Error Setting Mode\n");
618e6b09
MM
343// return;
344// }
345 write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_AUTO_NEG);
346
347 // Set EMAC address
348 setEmacAddr(mac_address);
349
350 /* Initialize Tx and Rx DMA Descriptors */
351 LPC_EMAC->RxDescriptor = (uint32_t) rxbuf.rxdesc;
352 LPC_EMAC->RxStatus = (uint32_t) rxbuf.rxstat;
d4ee6ee2 353 LPC_EMAC->RxDescriptorNumber = LPC17XX_RXBUFS-1;
618e6b09
MM
354
355 LPC_EMAC->TxDescriptor = (uint32_t) txbuf.txdesc;
356 LPC_EMAC->TxStatus = (uint32_t) txbuf.txstat;
d4ee6ee2 357 LPC_EMAC->TxDescriptorNumber = LPC17XX_TXBUFS-1;
618e6b09
MM
358
359 // Set Receive Filter register: enable broadcast and multicast
360 LPC_EMAC->RxFilterCtrl = EMAC_RFC_BCAST_EN | EMAC_RFC_PERFECT_EN;
361
362 /* Enable Rx Done and Tx Done interrupt for EMAC */
363 LPC_EMAC->IntEnable = EMAC_INT_RX_DONE | EMAC_INT_TX_DONE;
364
365 /* Reset all interrupts */
366 LPC_EMAC->IntClear = 0xFFFF;
367
368 /* Enable receive and transmit mode of MAC Ethernet core */
369 LPC_EMAC->Command = EMAC_CR_RX_EN | EMAC_CR_TX_EN | EMAC_CR_RMII | EMAC_CR_FULL_DUP | EMAC_CR_PASS_RUNT_FRM;
370 LPC_EMAC->MAC1 |= EMAC_MAC1_REC_EN;
371
d5c2e71c 372 DEBUG_PRINTF("ETH:EMAC INITIALISED\n");
618e6b09
MM
373}
374
375void LPC17XX_Ethernet::set_mac(uint8_t* newmac)
376{
377 memcpy(mac_address, newmac, 6);
378}
379
d5c2e71c 380// size must be preloaded with max size of packet buffer
d4ee6ee2 381bool LPC17XX_Ethernet::_receive_frame(void *packet, int *size)
618e6b09
MM
382{
383 if (can_read_packet() && can_write_packet())
384 {
385 int i = LPC_EMAC->RxConsumeIndex;
386 RX_Stat* stat = &(rxbuf.rxstat[i]);
d5c2e71c
JM
387 int len = (stat->Info & EMAC_RINFO_SIZE) + 1; //this is the index so add one to get the size
388 if(len <= *size) { // check against recieving buffer length
319567fa
JM
389 memcpy(packet, rxbuf.buf[i], len);
390 *size= len;
391 }else{
392 // discard frame that is too big for input buffer
d5c2e71c 393 DEBUG_PRINTF("WARNING: Discarded ethernet frame that is too big: %08lX, %d - %d\n", stat->Info, len, *size);
319567fa
JM
394 *size= 0;
395 }
618e6b09 396
d5c2e71c 397 //DEBUG_PRINTF("Received %d byte Ethernet frame %lu/%lu\n", *size, LPC_EMAC->RxProduceIndex, LPC_EMAC->RxConsumeIndex);
618e6b09
MM
398
399 uint32_t r = LPC_EMAC->RxConsumeIndex + 1;
400 if (r > LPC_EMAC->RxDescriptorNumber)
401 r = 0;
402 LPC_EMAC->RxConsumeIndex = r;
d4ee6ee2 403
319567fa 404 return *size > 0;
618e6b09 405 }
d4ee6ee2
JM
406
407 return false;
618e6b09
MM
408}
409
410void LPC17XX_Ethernet::irq()
411{
d4ee6ee2
JM
412 // if (EMAC_IntGetStatus(EMAC_INT_RX_DONE))
413 // {
414 // //_receive_frame();
415 // }
416
417 // if (EMAC_IntGetStatus(EMAC_INT_TX_DONE))
418 // {
419 // }
618e6b09
MM
420}
421
422bool LPC17XX_Ethernet::can_read_packet()
423{
424 return (LPC_EMAC->RxProduceIndex != LPC_EMAC->RxConsumeIndex);
425}
426
427int LPC17XX_Ethernet::read_packet(uint8_t** buf)
428{
429 *buf = rxbuf.buf[LPC_EMAC->RxConsumeIndex];
430 return rxbuf.rxstat[LPC_EMAC->RxConsumeIndex].Info & EMAC_RINFO_SIZE;
431}
432
433void LPC17XX_Ethernet::release_read_packet(uint8_t*)
434{
435 uint32_t r = LPC_EMAC->RxConsumeIndex + 1;
436 if (r > LPC_EMAC->RxDescriptorNumber)
437 r = 0;
438 LPC_EMAC->RxConsumeIndex = r;
439}
440
441bool LPC17XX_Ethernet::can_write_packet()
442{
443 uint32_t r = LPC_EMAC->TxProduceIndex + 1;
444 if (r > LPC_EMAC->TxDescriptorNumber)
445 r = 0;
446 return (r != LPC_EMAC->TxConsumeIndex);
447}
448
449int LPC17XX_Ethernet::write_packet(uint8_t* buf, int size)
450{
d4ee6ee2 451 txbuf.txdesc[LPC_EMAC->TxProduceIndex].control = ((size - 1) & 0x7ff) | EMAC_TCTRL_LAST | EMAC_TCTRL_CRC | EMAC_TCTRL_PAD | EMAC_TCTRL_INT;
618e6b09
MM
452
453 uint32_t r = LPC_EMAC->TxProduceIndex + 1;
454 if (r > LPC_EMAC->TxDescriptorNumber)
455 r = 0;
456
457 if (r == LPC_EMAC->TxConsumeIndex)
458 return 0;
459
460 LPC_EMAC->TxProduceIndex = r;
461
462 return size;
463}
464
465void* LPC17XX_Ethernet::request_packet_buffer()
466{
467 return txbuf.txdesc[LPC_EMAC->TxProduceIndex].packet;
468}
469
470NET_PACKET LPC17XX_Ethernet::get_new_packet_buffer(NetworkInterface* ni)
471{
472 if (ni != this)
473 return NULL;
474
475 return (NET_PACKET) request_packet_buffer();
476}
477
478NET_PAYLOAD LPC17XX_Ethernet::get_payload_buffer(NET_PACKET packet)
479{
480 return (NET_PAYLOAD) packet;
481}
482
483void LPC17XX_Ethernet::set_payload_length(NET_PACKET packet, int length)
484{
485 uint32_t offset = ((uint8_t*) packet) - txbuf.buf[0];
486 int i = (offset / LPC17XX_MAX_PACKET);
487 if ((i < LPC17XX_TXBUFS) && ((offset % LPC17XX_MAX_PACKET) == 0))
488 {
489 txbuf.txdesc[i].control = (txbuf.txdesc[i].control & ~EMAC_TCTRL_SIZE) | (length & EMAC_TCTRL_SIZE);
490 }
491}
492
493int LPC17XX_Ethernet::receive(NetworkInterface* ni, NET_PACKET packet, int length)
494{
495 if (can_write_packet())
496 return write_packet((uint8_t*) packet, length);
497 return 0;
498}
499
500int LPC17XX_Ethernet::construct(NetworkInterface* ni, NET_PACKET packet, int length)
501{
502 return length;
503}
504
505extern "C" {
506 void ENET_IRQHandler()
507 {
508 LPC17XX_Ethernet::instance->irq();
509 }
510}
511
512// void LPC17XX_Ethernet::provide_net(netcore* n)
513// {
514// NetworkInterface::provide_net(n);
515// up = false;
516// n->set_interface_status(this, up);
517// }
7cff8869
JM
518
519#endif