]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/devs/eth/arm/netarm/v2_0/src/netarm_eth_drv.c
ec72df7cba3831bf156b39a0cee9a242c25b2c34
[karo-tx-redboot.git] / packages / devs / eth / arm / netarm / v2_0 / src / netarm_eth_drv.c
1 //==========================================================================
2 //
3 //      netarm_eth_drv.c
4 //
5 //      NetSilion NET+ARM Ethernet Driver (DMA driven)
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 2005 eCosCentric LTD
12 //
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //==========================================================================
36 //#####DESCRIPTIONBEGIN####
37 //
38 // Author(s):           Harald Brandl (harald.brandl@fh-joanneum.at)
39 // Contributors:        Harald Brandl
40 // Date:                01.08.2004
41 // Purpose:             NET+ARM Ethernet Driver (DMA driven)
42 // Description:
43 //
44 //####DESCRIPTIONEND####
45 //
46 //==========================================================================
47
48 #include <cyg/infra/cyg_type.h>
49 #include <cyg/hal/hal_arch.h>
50 #include <cyg/infra/diag.h>
51 #include <cyg/hal/drv_api.h>
52 #include <cyg/io/eth/netdev.h>
53 #include <cyg/io/eth/eth_drv.h>
54
55 #include <pkgconf/devs_eth_arm_netarm.h>
56 #include <cyg/hal/hal_platform_ints.h>
57 #include "eth_regs.h"
58 #include "MII.h"
59 #include "netarm_eth_drv.h"
60 #include "eeprom.h"
61
62 #include <cyg/hal/hal_io.h>
63
64 // FIXME: The HAL should provide this
65 #define CYGNUM_HAL_INTERRUPT_DMA2               31
66 #define CYGNUM_HAL_INTERRUPT_DMA1               32
67
68 // FIXME: The HAL should provide this and it should handle more than
69 // RAM addresses
70 #define HAL_VIRT_TO_PHYS_ADDRESS( vaddr ) (unsigned char *)vaddr - 0x8000000
71
72 #define BufferSizeA 128
73 #define BufferSizeB 512
74 #define BufferSizeC 1524
75
76 #define NumA 16
77 #define NumB 8
78 #define NumC 8
79
80 #define EEPROM_MAC 0    // location of MAC address inside eeprom
81
82 static cyg_mutex_t Key_Mutex;
83 static private_data_t driver_private;
84
85 static volatile unsigned char RxBufferA[NumA][BufferSizeA];
86 static volatile unsigned char RxBufferB[NumB][BufferSizeB];
87 static volatile unsigned char RxBufferC[NumC][BufferSizeC];
88
89 static volatile unsigned char TxBuffer[1500];
90 static volatile unsigned char TxHeader[14];
91
92 static volatile BDP_t RxBDP_A[NumA];
93 static volatile BDP_t RxBDP_B[NumB];
94 static volatile BDP_t RxBDP_C[NumC];
95
96 static volatile BDP_t TxBDP[2];
97
98 // relocation pointer for data accessed by DMA to enable caching
99 static volatile unsigned char *pRxBufferA, *pRxBufferB, *pRxBufferC;
100 static volatile unsigned char *pTxHeader, *pTxBuffer;
101 static volatile BDP_t *pRxBDP_A, *pRxBDP_B, *pRxBDP_C;
102 static volatile BDP_t *pTxBDP;
103
104 ETH_DRV_SC(netarm_sc,
105            (void *)&driver_private,     // driver specific data
106            "eth0",                      // Name for this interface
107            netarm_start,
108            netarm_stop,
109            netarm_control,
110            netarm_can_send,
111            netarm_send,
112            netarm_recv,
113            netarm_deliver,
114            netarm_poll,
115            netarm_int_vector);
116
117 NETDEVTAB_ENTRY(netarm_netdev,
118                 "ETH_DRV",
119                 netarm_init,
120                 &netarm_sc);
121
122 static void
123 fastcopy(void *buf, void *data, unsigned long len)
124 {
125   asm volatile(
126                
127                "STMDB SP!, {R11};"
128                
129                "TST R1, #2;"                    // test if aligned
130                "LDRNEH R3, [R1], #2;"
131                "STRNEH R3, [R0], #2;"
132                "SUBNE R2, R2, #2;"
133                "TST R1, #1;"
134                "LDRNEB R3, [R1], #1;"
135                "STRNEB R3, [R0], #1;"
136                "SUBNE R2, R2, #1;"
137                
138                ".START:"
139                
140                "CMP R2, #44;"
141                "BLT .LASTBYTES;"
142                "LDMIA R1!, {R3 - R12, R14};"
143                "STMIA R0!, {R3 - R12, R14};"
144                "SUB R2, R2, #44;"
145                
146                "CMP R2, #44;"
147                "BLT .LASTBYTES;"
148                "LDMIA R1!, {R3 - R12, R14};"
149                "STMIA R0!, {R3 - R12, R14};"
150                "SUB R2, R2, #44;"
151                
152                "CMP R2, #44;"
153                "BLT .LASTBYTES;"
154                "LDMIA R1!, {R3 - R12, R14};"
155                "STMIA R0!, {R3 - R12, R14};"
156                "SUB R2, R2, #44;"
157                
158                "CMP R2, #44;"
159                "BLT .LASTBYTES;"
160                "LDMIA R1!, {R3 - R12, R14};"
161                "STMIA R0!, {R3 - R12, R14};"
162                "SUB R2, R2, #44;"
163                
164                "CMP R2, #44;"
165                "BLT .LASTBYTES;"
166                "LDMIA R1!, {R3 - R12, R14};"
167                "STMIA R0!, {R3 - R12, R14};"
168                "SUB R2, R2, #44;"
169                
170                "CMP R2, #44;"
171                "BLT .LASTBYTES;"
172                "LDMIA R1!, {R3 - R12, R14};"
173                "STMIA R0!, {R3 - R12, R14};"
174                "SUB R2, R2, #44;"
175                
176                "CMP R2, #44;"
177                "BLT .LASTBYTES;"
178                "LDMIA R1!, {R3 - R12, R14};"
179                "STMIA R0!, {R3 - R12, R14};"
180                "SUB R2, R2, #44;"
181                
182                "CMP R2, #44;"
183                "BLT .LASTBYTES;"
184                "LDMIA R1!, {R3 - R12, R14};"
185                "STMIA R0!, {R3 - R12, R14};"
186                "SUB R2, R2, #44;"
187                
188                "CMP R2, #44;"
189                "BLT .LASTBYTES;"
190                "LDMIA R1!, {R3 - R12, R14};"
191                "STMIA R0!, {R3 - R12, R14};"
192                "SUB R2, R2, #44;"
193                
194                "CMP R2, #44;"
195                "BLT .LASTBYTES;"
196                "LDMIA R1!, {R3 - R12, R14};"
197                "STMIA R0!, {R3 - R12, R14};"
198                "SUB R2, R2, #44;"
199                
200                "BGE .START;"
201                
202                
203                ".LASTBYTES:"
204                
205                "AND R14, R2, #0xfffffffc;"
206                "LDR PC, [PC, R14];"
207                "NOP;"
208                
209                ".SWITCH:"
210                ".word   .CASE0;"
211                ".word   .CASE1;"
212                ".word   .CASE2;"
213                ".word   .CASE3;"
214                ".word   .CASE4;"
215                ".word   .CASE5;"
216                ".word   .CASE6;"
217                ".word   .CASE7;"
218                ".word   .CASE8;"
219                ".word   .CASE9;"
220                ".word   .CASE10;"
221                
222                ".CASE0:"
223                "B .END;"
224                
225                ".CASE1:"
226                "LDR R3, [R1]!;"
227                "STR R3, [R0]!;"
228                "B .END;"
229                
230                ".CASE2:"
231                "LDMIA R1!, {R3, R4};"
232                "STMIA R0!, {R3, R4};"
233                "B .END;"
234                
235                ".CASE3:"
236                "LDMIA R1!, {R3 - R5};"
237                "STMIA R0!, {R3 - R5};"
238                "B .END;"
239                
240                ".CASE4:"
241                "LDMIA R1!, {R3 - R6};"
242                "STMIA R0!, {R3 - R6};"
243                "B .END;"
244                
245                ".CASE5:"
246                "LDMIA R1!, {R3 - R7};"
247                "STMIA R0!, {R3 - R7};"
248                "B .END;"
249                
250                ".CASE6:"
251                "LDMIA R1!, {R3 - R8};"
252                "STMIA R0!, {R3 - R8};"
253                "B .END;"
254                
255                ".CASE7:"
256                "LDMIA R1!, {R3 - R9};"
257                "STMIA R0!, {R3 - R9};"
258                "B .END;"
259                
260                ".CASE8:"
261                "LDMIA R1!, {R3 - R10};"
262                "STMIA R0!, {R3 - R10};"
263                "B .END;"
264                
265                ".CASE9:"
266                "LDMIA R1!, {R3 - R11};"
267                "STMIA R0!, {R3 - R11};"
268                "B .END;"
269                
270                ".CASE10:"
271                "LDMIA R1!, {R3 - R12};"
272                "STMIA R0!, {R3 - R12};"
273                
274                ".END:"
275                "TST R2, #2;"
276                "LDRNEH R3, [R1], #2;"
277                "STRNEH R3, [R0], #2;"
278                "TST R2, #1;"
279                "LDRNEB R3, [R1], #1;"
280                "STRNEB R3, [R0], #1;"
281                
282                "LDMIA SP!, {R11};"
283                
284                :
285                : "r" (buf), "r" (data), "r" (len)
286                : "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14"
287                );
288 }
289
290 static bool
291 KeyBufferFull(private_data_t *pd)
292 {
293   int tmp = 0;
294   
295   cyg_drv_mutex_lock(&Key_Mutex);
296   
297   if((pd->key_head + 1) % MaxKeys == pd->key_tail)
298     {
299       tmp = 1;
300     }
301   
302   cyg_drv_mutex_unlock(&Key_Mutex);
303   
304   return tmp;
305 }
306
307 static void
308 AddKey(unsigned long key, private_data_t *pd)
309 {
310   
311   cyg_drv_mutex_lock(&Key_Mutex);
312   
313   pd->KeyBuffer[pd->key_head] = key;
314   pd->key_head = (pd->key_head + 1) % MaxKeys;
315   
316   cyg_drv_mutex_unlock(&Key_Mutex);
317 }
318
319 static unsigned
320 GetKey(private_data_t *pd)
321 {
322   unsigned key = 0;
323   
324   cyg_drv_mutex_lock(&Key_Mutex);
325   
326   if(pd->key_tail != pd->key_head)
327     {
328       key = pd->KeyBuffer[pd->key_tail];
329       pd->key_tail = (pd->key_tail + 1) % MaxKeys;
330     }
331   
332   cyg_drv_mutex_unlock(&Key_Mutex);
333   
334   return key;
335 }
336
337 static cyg_uint32
338 dma_rx_isr(cyg_vector_t vector, cyg_addrword_t data)
339 {
340   
341   // block this interrupt until the dsr completes
342   cyg_drv_interrupt_mask(vector);
343   
344   // tell ecos to allow further interrupt processing
345   cyg_drv_interrupt_acknowledge(vector);
346   
347   return CYG_ISR_CALL_DSR;      // call the dsr
348 }
349
350 static void
351 dma_rx_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
352 {
353   
354   eth_drv_dsr( vector, count, data );
355   
356   DMA1A_SR = 0x80000000;                // acknowledge and mask interrupts
357   DMA1B_SR = 0x80000000;
358   DMA1C_SR = 0x80000000;
359   
360   cyg_drv_interrupt_unmask(vector);
361 }
362
363 static cyg_uint32
364 dma_tx_isr(cyg_vector_t vector, cyg_addrword_t data)
365 {
366   
367   // block this interrupt until the dsr completes
368   cyg_drv_interrupt_mask(vector);
369   
370   // tell ecos to allow further interrupt processing
371   cyg_drv_interrupt_acknowledge(vector);
372   
373   return CYG_ISR_CALL_DSR;      // invoke the dsr
374 }
375
376 static void
377 dma_tx_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
378 {
379   
380   eth_drv_dsr( vector, count, data );
381   
382   DMA2_SR |= 0x80000000; // acknowledge interrupt
383   
384   cyg_drv_interrupt_unmask(vector);
385 }
386
387 static void
388 SetupDMA(void)
389 {
390   int i;
391   
392   pRxBufferA = (unsigned char *)HAL_VIRT_TO_PHYS_ADDRESS(RxBufferA);
393   pRxBufferB = (unsigned char *)HAL_VIRT_TO_PHYS_ADDRESS(RxBufferB);
394   pRxBufferC = (unsigned char *)HAL_VIRT_TO_PHYS_ADDRESS(RxBufferC);
395   
396   pTxBuffer = (unsigned char *)HAL_VIRT_TO_PHYS_ADDRESS(TxBuffer);
397   pTxHeader = (unsigned char *)HAL_VIRT_TO_PHYS_ADDRESS(TxHeader);
398   
399   pRxBDP_A = (BDP_t *)HAL_VIRT_TO_PHYS_ADDRESS(RxBDP_A);
400   pRxBDP_B = (BDP_t *)HAL_VIRT_TO_PHYS_ADDRESS(RxBDP_B);
401   pRxBDP_C = (BDP_t *)HAL_VIRT_TO_PHYS_ADDRESS(RxBDP_C);
402   
403   pTxBDP = (BDP_t *)((unsigned char *)TxBDP);
404   
405   *SYSCON |= 0x40;              // reset DMA module
406   
407   for(i = 0; i < NumA; i++)
408     {
409       pRxBDP_A[i].lo = ((unsigned)(pRxBufferA+i*BufferSizeA)) & 0x3fffffff;
410       pRxBDP_A[i].hi = BufferSizeA;
411     }
412   
413   pRxBDP_A[i - 1].lo |= 0x80000000; // set W bit
414   
415   for(i = 0; i < NumB; i++)
416     {
417       pRxBDP_B[i].lo = ((unsigned)(pRxBufferB+i*BufferSizeB)) & 0x3fffffff;
418       pRxBDP_B[i].hi = BufferSizeB;
419     }
420   
421   pRxBDP_B[i - 1].lo |= 0x80000000;
422   
423   for(i = 0; i < NumC; i++)
424     {
425       pRxBDP_C[i].lo = ((unsigned)(pRxBufferC+i*BufferSizeC)) & 0x3fffffff;
426       pRxBDP_C[i].hi = BufferSizeC;
427     }
428   
429   pRxBDP_C[i - 1].lo |= 0x80000000;
430   
431   *SYSCON &= ~0x40;
432   
433   DMA1A_BDP = (unsigned)pRxBDP_A;
434   DMA1A_CR = 0x82000000;        //burst transfer
435   DMA1A_SR = 0xa00000;
436   
437   DMA1B_BDP = (unsigned)pRxBDP_B;
438   DMA1B_CR = 0x82000000;        //burst transfer
439   DMA1B_SR = 0xa00000;
440   
441   DMA1C_BDP = (unsigned)pRxBDP_C;
442   DMA1C_CR = 0x82000000;        //burst transfer
443   DMA1C_SR = 0xa00000;
444   
445   
446   pTxBDP[0].lo = ((unsigned)pTxHeader) & 0x3fffffff;
447   pTxBDP[1].lo = ((unsigned)pTxBuffer) & 0x3fffffff;
448   pTxBDP[1].lo |= 0xa0000000;   // set W and L bit
449   
450   DMA2_BDP = (unsigned)pTxBDP;
451   DMA2_CR = 0x86000000; //burst transfer
452   DMA2_SR = 0x800000;
453   
454 }
455
456 static bool
457 netarm_init(struct cyg_netdevtab_entry *tab)
458 {
459   struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance;
460   cyg_bool duplex;
461   static cyg_interrupt dma_rx_int_object, dma_tx_int_object;
462   static cyg_handle_t dma_rx_int_handle, dma_tx_int_handle;
463   
464 #ifdef CYGSEM_DEVS_ETH_ARM_NETARM_ETH0_SET_ESA
465   
466   unsigned char esa[6] = CYGDAT_DEVS_ETH_ARM_NETARM_ETH0_ESA;
467 #else
468   unsigned char esa[6];
469   
470   initI2C();
471   eepromRead(0x50, EEPROM_MAC, esa, 6);
472 #endif
473   
474   // setup dma receiver
475   SetupDMA();
476   
477   mii_reset();
478   mii_negotiate();                      // initialize PHY
479   duplex = mii_check_duplex();
480   
481   // Ethernet Controller Initializatition
482   
483   MACCR = (0x1c | (duplex << 1));       // auto CRC, late collision retry
484   STLCR = 0x3;                          // insert MAC source address
485                                         // into ethernet frame
486   BtBIPGGapTimerR = 0x14;               // standard values
487   NonBtBIPGGapTimerR  = ((0x9 << 7) | 0x11);    // standard values
488   CollWinR = ((0x37 << 8) | 0xf);       // standard values
489   SAFR = 0x1;                           // broadcast mode
490   EthGenCR = (0x40400400 | (duplex << 16)); // dma mode, full duplex,
491                                             // enable pNA mode(needed
492                                             // for alignment)
493   
494   cyg_drv_interrupt_create(CYGNUM_HAL_INTERRUPT_DMA1,   // Interrupt Vector
495                            0,                           // Interrupt Priority
496                            (cyg_addrword_t)&netarm_sc,  // Reference
497                                                         // to Driver
498                                                         // Instance
499                            dma_rx_isr,
500                            dma_rx_dsr,
501                            &dma_rx_int_handle,
502                            &dma_rx_int_object);
503   
504   cyg_drv_interrupt_create(CYGNUM_HAL_INTERRUPT_DMA2,   // Interrupt Vector
505                            0,                           // Interrupt Priority
506                            (cyg_addrword_t)&netarm_sc,  // Reference
507                                                         // to Driver
508                                                         // Instance
509                            dma_tx_isr,
510                            dma_tx_dsr,
511                            &dma_tx_int_handle,
512                            &dma_tx_int_object);
513   
514   cyg_drv_interrupt_attach(dma_rx_int_handle);
515   cyg_drv_interrupt_attach(dma_tx_int_handle);
516   
517   cyg_mutex_init(&Key_Mutex);
518   
519   sc->funs->eth_drv->init(sc, esa);
520   
521   return true;
522 }
523
524 static void
525 netarm_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len)
526 {
527   int i, len;
528   private_data_t *pd = (private_data_t *)(sc->driver_private);
529   unsigned char *data, *buf = pd->RxBuffer;
530   
531   for (i = 0;  i < sg_len;  i++) {
532     data = (unsigned char *)(sg_list[i].buf);
533     len = sg_list[i].len;
534     if (len)
535       {
536         if(i == 1)
537           {
538             buf += 2;
539           }
540         
541         fastcopy(data, buf, len);
542         buf += len;
543       }
544   }
545 }
546
547 static void
548 netarm_deliver(struct eth_drv_sc *sc)
549 {
550   static int a = 0, b = 0, c = 0;
551   unsigned long key;
552   private_data_t *pd = (private_data_t *)(sc->driver_private);
553   
554   while((key = GetKey(pd)))
555     {
556       sc->funs->eth_drv->tx_done(sc, key, 0);
557     }
558   
559   while(pRxBDP_A[a].hi & 0x8000)
560     {
561       pd->RxBuffer = (unsigned char *)(pRxBDP_A[a].lo & 0x1FFFFFFF);
562       HAL_REORDER_BARRIER();
563       sc->funs->eth_drv->recv(sc, pRxBDP_A[a].hi & 0x7FFF);
564       HAL_REORDER_BARRIER();
565       pRxBDP_A[a].hi = BufferSizeA;
566       HAL_REORDER_BARRIER();
567       a = (a + 1) % NumA;
568     }
569   
570   while(pRxBDP_B[b].hi & 0x8000)
571     {
572       pd->RxBuffer = (unsigned char *)(pRxBDP_B[b].lo & 0x1FFFFFFF);
573       HAL_REORDER_BARRIER();
574       sc->funs->eth_drv->recv(sc, pRxBDP_B[b].hi & 0x7FFF);
575       HAL_REORDER_BARRIER();
576       pRxBDP_B[b].hi = BufferSizeB;
577       HAL_REORDER_BARRIER();
578       b = (b + 1) % NumB;
579     }
580   
581   while(pRxBDP_C[c].hi & 0x8000)
582     {
583       pd->RxBuffer = (unsigned char *)(pRxBDP_C[c].lo & 0x1FFFFFFF);
584       HAL_REORDER_BARRIER();
585       sc->funs->eth_drv->recv(sc, pRxBDP_C[c].hi & 0x7FFF);
586       HAL_REORDER_BARRIER();
587       pRxBDP_C[c].hi = BufferSizeC;
588       HAL_REORDER_BARRIER();
589       c = (c + 1) % NumC;
590     }
591   
592   if((DMA1A_SR & 0x20000000) || (DMA1B_SR & 0x20000000) || (DMA1C_SR & 0x20000000))
593     {
594       EthGenCR &= ~0xc0000000;          // reset Rx FIFO
595       EthGenCR |= 0xc0000000;
596     }
597   
598   DMA1A_SR = 0x20a00000;
599   DMA1B_SR = 0x20a00000;
600   DMA1C_SR = 0x20a00000;
601 }
602
603 static int
604 netarm_can_send(struct eth_drv_sc *sc)
605 {
606   private_data_t *pd = (private_data_t *)(sc->driver_private);
607   
608   if((pTxBDP[0].hi & 0x8000) || (pTxBDP[1].hi & 0x8000) || KeyBufferFull(pd))
609     return 0;
610   
611   return 1;
612 }
613
614 static void
615 netarm_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list,
616                         int sg_len, int total_len, unsigned long key)
617 {
618   private_data_t *pd = (private_data_t *)(sc->driver_private);
619   int i, len;
620   unsigned char *data;
621   volatile char *buf = pTxBuffer;
622   
623   AddKey(key, pd);
624   
625   // Put data into buffer
626   for (i = 0;  i < sg_len;  i++) {
627     data = (unsigned char *)sg_list[i].buf;
628     len = sg_list[i].len;
629     
630     if(i == 0)
631       {
632         if((unsigned long)data & 0x3)
633           {
634             memcpy((unsigned char*)pTxHeader, data, 0xe);
635           }
636         else
637           {
638             fastcopy((unsigned char *)pTxHeader, data, 0xe);
639           }
640         
641         len -= 0xe;
642         data += 0xe;
643       }
644     
645     if (len)
646       {
647         fastcopy((unsigned char *)buf, data, len);
648         buf += len;
649       }
650   }
651   
652   cyg_drv_dsr_lock();
653   pTxBDP[0].hi = 0x800e;
654   HAL_REORDER_BARRIER();
655   pTxBDP[1].hi = (total_len - 0xe) | 0x8000;
656   HAL_REORDER_BARRIER();
657   DMA2_SR |= 0xf0000000;
658   cyg_drv_dsr_unlock();
659 }
660
661 static void
662 netarm_start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags)
663 {
664   SetMAC(enaddr);                       // set MAC address
665   HAL_REORDER_BARRIER();
666   EthGenCR |= 0x80800000;       // enable Rx und Tx FIFO
667   HAL_REORDER_BARRIER();
668   cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_DMA1);
669   cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_DMA2);
670 }
671
672 static void
673 netarm_stop(struct eth_drv_sc *sc)
674 {
675   EthGenCR &= 0x7f7fffff;
676   HAL_REORDER_BARRIER();
677   cyg_drv_interrupt_mask(CYGNUM_HAL_INTERRUPT_DMA1);
678   cyg_drv_interrupt_mask(CYGNUM_HAL_INTERRUPT_DMA2);
679 }
680
681 static int
682 netarm_control(struct eth_drv_sc *sc, unsigned long key, void *data, int len)
683 {
684   switch (key)
685     {
686     case ETH_DRV_SET_MAC_ADDRESS:
687       return 0;
688       break;
689     case ETH_DRV_SET_MC_LIST:
690     case ETH_DRV_SET_MC_ALL:
691       return 0;
692     default:
693       return 1;
694       break;
695     }
696 }
697
698 static void
699 netarm_poll(struct eth_drv_sc *sc)
700 {
701 }
702
703 static int
704 netarm_int_vector(struct eth_drv_sc *sc)
705 {
706   return CYGNUM_HAL_INTERRUPT_DMA1;
707 }
708
709 static void
710 SetMAC(unsigned char *esa)
711 {
712   SAR1 = (esa[1] << 8) | esa[0];        // set MAC address
713   SAR2 = (esa[3] << 8) | esa[2];
714   SAR3 = (esa[5] << 8) | esa[4];
715 }