2 #include <aros/debug.h>
3 #include <aros/macros.h>
4 #include <asm/amcc440.h>
8 #include <proto/kernel.h>
10 #include <proto/utility.h>
11 #include <proto/processor.h>
13 #include <utility/utility.h>
14 #include <utility/hooks.h>
15 #include <utility/tagitem.h>
17 #include <resources/processor.h>
20 #include LC_LIBDEFS_FILE
22 // TODO: Implement CmdFlush!!!!!!!!!
24 static void EMAC_UDelay(struct EMACUnit
*unit
, uint32_t usec
)
26 unit
->eu_TimerPort
.mp_SigTask
= FindTask(NULL
);
27 unit
->eu_TimerRequest
.tr_node
.io_Command
= TR_ADDREQUEST
;
28 unit
->eu_TimerRequest
.tr_time
.tv_secs
= usec
/ 1000000;
29 unit
->eu_TimerRequest
.tr_time
.tv_micro
= usec
% 1000000;
31 DoIO((struct IORequest
*)&unit
->eu_TimerRequest
);
34 static int EMAC_Start(struct EMACUnit
*unit
)
38 uint32_t reg
, mode_reg
, speed
, duplex
;
41 D(bug("[EMAC%d] start()\n", unit
->eu_UnitNum
));
44 * Enable MAL channels:
45 * TX Channels 0 and 1 are assigned to unit 0, Channels 2 and 3 are assigned to unit 1.
46 * RX Channel 0 is assigned to unit 0, channel 1 is assigned to unit 1.
49 D(bug("[EMAC%d] Enable MAL\n", unit
->eu_UnitNum
));
50 wrdcr(MAL0_RXCASR
, 0x80000000 >> unit
->eu_UnitNum
);
51 wrdcr(MAL0_TXCASR
, 0x80000000 >> (2*unit
->eu_UnitNum
));
56 unit
->udelay(unit
, 100);
57 outl((ZMII_FER_RMII
| ZMII_FER_MDI
) << ZMII_FER_V (unit
->eu_UnitNum
), ZMII_FER
);
58 outl(ZMII_SSR_SP
<< ZMII_SSR_V(unit
->eu_UnitNum
), ZMII_SSR
);
61 outl(EMAC_M0_SRST
, EMAC_M0
+ unit
->eu_IOBase
);
62 while(inl(EMAC_M0
+ unit
->eu_IOBase
) & EMAC_M0_SRST
)
63 unit
->udelay(unit
, 1000);
65 EMAC_miiphy_reset(unit
);
67 /* Start/Restart autonegotiation */
68 EMAC_phy_setup_aneg(unit
);
69 unit
->udelay(unit
, 1000);
71 EMAC_miiphy_read (unit
, PHY_BMSR
, ®_short
);
74 * Wait if PHY is capable of autonegotiation and autonegotiation is not complete
76 if ((reg_short
& PHY_BMSR_AUTN_ABLE
)
77 && !(reg_short
& PHY_BMSR_AUTN_COMP
)) {
78 D(bug("[EMAC%d] Waiting for PHY auto negotiation to complete", unit
->eu_UnitNum
));
80 while (!(reg_short
& PHY_BMSR_AUTN_COMP
)) {
85 D(bug(" TIMEOUT !\n"));
89 if ((i
++ % 1000) == 0) {
92 unit
->udelay (unit
, 1000); /* 1 ms */
93 EMAC_miiphy_read (unit
, PHY_BMSR
, ®_short
);
97 unit
->udelay (unit
, 500000); /* another 500 ms (results in faster booting) */
100 speed
= EMAC_miiphy_speed (unit
);
101 duplex
= EMAC_miiphy_duplex (unit
);
103 D(bug("[EMAC%d] Speed is %d Mbps - %s duplex connection\n", unit
->eu_UnitNum
,
104 (int) speed
, (duplex
== HALF
) ? "HALF" : "FULL"));
106 stack
= SuperState();
107 wrdcr(SDR0_CFGADDR
, SDR0_MFR
);
108 reg
= rddcr(SDR0_CFGDATA
);
110 reg
= (reg
& ~SDR0_MFR_ZMII_MODE_MASK
) | SDR0_MFR_ZMII_MODE_RMII_100M
;
112 reg
= (reg
& ~SDR0_MFR_ZMII_MODE_MASK
) | SDR0_MFR_ZMII_MODE_RMII_10M
;
114 wrdcr(SDR0_CFGADDR
, SDR0_MFR
);
115 wrdcr(SDR0_CFGDATA
, reg
);
118 /* Set ZMII/RGMII speed according to the phy link speed */
120 if ( (speed
== 100) || (speed
== 1000) )
121 outl (reg
| (ZMII_SSR_SP
<< ZMII_SSR_V (unit
->eu_UnitNum
)), ZMII_SSR
);
123 outl (reg
& (~(ZMII_SSR_SP
<< ZMII_SSR_V (unit
->eu_UnitNum
))), ZMII_SSR
);
125 /* set transmit enable & receive enable */
126 outl (EMAC_M0_TXE
| EMAC_M0_RXE
, EMAC_M0
+ unit
->eu_IOBase
);
128 /* set receive fifo to 4k and tx fifo to 2k */
129 mode_reg
= inl (EMAC_M1
+ unit
->eu_IOBase
);
130 mode_reg
|= EMAC_M1_RFS_4K
| EMAC_M1_TX_FIFO_2K
;
133 if (speed
== _1000BASET
) {
134 mode_reg
= mode_reg
| EMAC_M1_MF_1000MBPS
| EMAC_M1_IST
;
135 } else if (speed
== _100BASET
)
136 mode_reg
= mode_reg
| EMAC_M1_MF_100MBPS
| EMAC_M1_IST
;
138 mode_reg
= mode_reg
& ~0x00C00000; /* 10 MBPS */
140 mode_reg
= mode_reg
| 0x80000000 | EMAC_M1_IST
;
142 outl (mode_reg
, EMAC_M1
+ unit
->eu_IOBase
);
144 /* Enable broadcast and indvidual address */
145 /* TBS: enabling runts as some misbehaved nics will send runts */
146 outl (EMAC_RMR_BAE
| EMAC_RMR_IAE
, EMAC_RXM
+ unit
->eu_IOBase
);
148 /* we probably need to set the tx mode1 reg? maybe at tx time */
150 /* set transmit request threshold register */
151 outl (0x18000000, EMAC_TRTR
+ unit
->eu_IOBase
); /* 256 byte threshold */
153 /* set receive low/high water mark register */
154 /* 440s has a 64 byte burst length */
155 outl (0x80009000, EMAC_RX_HI_LO_WMARK
+ unit
->eu_IOBase
);
157 outl (0xf8640000, EMAC_TXM1
+ unit
->eu_IOBase
);
159 /* Set fifo limit entry in tx mode 0 */
160 outl (0x00000003, EMAC_TXM0
+ unit
->eu_IOBase
);
162 outl (0x00000008, EMAC_I_FRAME_GAP_REG
+ unit
->eu_IOBase
);
165 unit
->eu_IER
= EMAC_ISR_PTLE
| EMAC_ISR_BFCS
| EMAC_ISR_ORE
| EMAC_ISR_IRE
;
166 if (speed
== _100BASET
)
167 unit
->eu_IER
= unit
->eu_IER
| EMAC_ISR_SYE
;
169 outl (0xffffffff, EMAC_ISR
+ unit
->eu_IOBase
); /* clear pending interrupts */
170 outl (unit
->eu_IER
, EMAC_IER
+ unit
->eu_IOBase
);
172 unit
->eu_Flags
|= IFF_UP
;
177 static int EMAC_Stop(struct EMACUnit
*unit
)
182 D(bug("[EMAC%d] stop()\n", unit
->eu_UnitNum
));
184 unit
->eu_Flags
&= ~IFF_UP
;
186 /* Stop MAL channels */
187 stack
= SuperState();
189 D(bug("[EMAC%d] Disable and reset MAL\n", unit
->eu_UnitNum
));
190 wrdcr(MAL0_RXCARR
, 0x80000000 >> unit
->eu_UnitNum
);
191 wrdcr(MAL0_TXCARR
, 0xc0000000 >> (2*unit
->eu_UnitNum
));
193 casr
= rddcr(MAL0_RXCASR
);
196 /* Wait for Reset to complete */
197 while(casr
& (0x80000000 >> unit
->eu_UnitNum
))
199 unit
->udelay(unit
, 1000);
201 stack
= SuperState();
202 casr
= rddcr(MAL0_RXCASR
);
207 outl(EMAC_M0_SRST
, EMAC_M0
+ unit
->eu_IOBase
);
209 D(bug("[EMAC%d] stopped\n", unit
->eu_UnitNum
));
214 static void EMAC_SetMacAddress(struct EMACUnit
*unit
)
218 D(bug("[EMAC%d] set_mac_address()\n", unit
->eu_UnitNum
));
219 D(bug("[EMAC%d] New addr=%02x:%02x:%02x:%02x:%02x:%02x\n", unit
->eu_UnitNum
,
220 unit
->eu_DevAddr
[0],unit
->eu_DevAddr
[1],
221 unit
->eu_DevAddr
[2],unit
->eu_DevAddr
[3],
222 unit
->eu_DevAddr
[4],unit
->eu_DevAddr
[5]));
226 reg
|= unit
->eu_DevAddr
[0];
228 reg
|= unit
->eu_DevAddr
[1];
230 outl (reg
, EMAC_IAH
+ unit
->eu_IOBase
);
234 reg
|= unit
->eu_DevAddr
[2];
236 reg
|= unit
->eu_DevAddr
[3];
238 reg
|= unit
->eu_DevAddr
[4];
240 reg
|= unit
->eu_DevAddr
[5];
242 outl (reg
, EMAC_IAL
+ unit
->eu_IOBase
);
246 * Report incoming events to all hyphotetical event receivers
248 VOID
ReportEvents(struct EMACBase
*EMACBase
, struct EMACUnit
*unit
, ULONG events
)
250 struct IOSana2Req
*request
, *tail
, *next_request
;
253 list
= &unit
->eu_RequestPorts
[EVENT_QUEUE
]->mp_MsgList
;
254 next_request
= (APTR
)list
->lh_Head
;
255 tail
= (APTR
)&list
->lh_Tail
;
257 /* Go through list of event listeners. If send messages to receivers if event found */
259 while(next_request
!= tail
)
261 request
= next_request
;
262 next_request
= (APTR
)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
264 if((request
->ios2_WireError
&events
) != 0)
266 request
->ios2_WireError
= events
;
267 Remove((APTR
)request
);
268 ReplyMsg((APTR
)request
);
276 VOID
CopyPacket(struct EMACBase
*EMACBase
, struct EMACUnit
*unit
,
277 struct IOSana2Req
*request
, UWORD packet_size
, UWORD packet_type
,
278 struct eth_frame
*buffer
)
280 struct Opener
*opener
;
281 BOOL filtered
= FALSE
;
282 UBYTE
*ptr
, *address
;
284 D(bug("[EMAC%d] CopyPacket(packet @ %x, len = %d)\n", unit
->eu_UnitNum
, buffer
, packet_size
));
286 /* Set multicast and broadcast flags */
288 request
->ios2_Req
.io_Flags
&= ~(SANA2IOF_BCAST
| SANA2IOF_MCAST
);
289 address
= buffer
->eth_packet_dest
;
290 if((*((ULONG
*)address
) == 0xffffffff) &&
291 (*((UWORD
*)(address
+ 4)) == 0xffff))
293 request
->ios2_Req
.io_Flags
|= SANA2IOF_BCAST
;
294 D(bug("[EMAC%d] CopyPacket: BROADCAST Flag set\n", unit
->eu_UnitNum
));
296 else if((buffer
->eth_packet_dest
[0] & 0x1) != 0)
298 request
->ios2_Req
.io_Flags
|= SANA2IOF_MCAST
;
299 D(bug("[EMAC%d] CopyPacket: MULTICAST Flag set\n", unit
->eu_UnitNum
));
302 /* Set source and destination addresses and packet type */
303 CopyMem(buffer
->eth_packet_source
, request
->ios2_SrcAddr
, ETH_ADDRESSSIZE
);
304 CopyMem(buffer
->eth_packet_dest
, request
->ios2_DstAddr
, ETH_ADDRESSSIZE
);
305 request
->ios2_PacketType
= packet_type
;
307 /* Adjust for cooked packet request */
309 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
311 packet_size
-= ETH_PACKET_DATA
;
312 ptr
= (UBYTE
*)&buffer
->eth_packet_data
[0];
316 ptr
= (UBYTE
*)buffer
;
319 request
->ios2_DataLength
= packet_size
;
320 D(bug("[EMAC%d] CopyPacket: packet @ %x (%d bytes)\n", unit
->eu_UnitNum
, ptr
, packet_size
));
324 opener
= request
->ios2_BufferManagement
;
325 if((request
->ios2_Req
.io_Command
== CMD_READ
) &&
326 (opener
->filter_hook
!= NULL
))
327 if(!CallHookPkt(opener
->filter_hook
, request
, ptr
))
329 D(bug("[EMAC%d] CopyPacket: packet filtered\n", unit
->eu_UnitNum
));
335 /* Copy packet into opener's buffer and reply packet */
336 D(bug("[EMAC%d] CopyPacket: opener recieve packet .. ", unit
->eu_UnitNum
));
337 if(!opener
->rx_function(request
->ios2_Data
, ptr
, packet_size
))
339 D(bug("ERROR occured!!\n"));
340 request
->ios2_Req
.io_Error
= S2ERR_NO_RESOURCES
;
341 request
->ios2_WireError
= S2WERR_BUFF_ERROR
;
342 ReportEvents(EMACBase
, unit
, S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
| S2EVENT_RX
);
346 D(bug("SUCCESS!!\n"));
349 Remove((APTR
)request
);
351 ReplyMsg((APTR
)request
);
352 D(bug("[EMAC%d] CopyPacket: opener notified.\n", unit
->eu_UnitNum
));
356 BOOL
AddressFilter(struct EMACBase
*EMACBase
, struct EMACUnit
*unit
, UBYTE
*address
)
358 struct AddressRange
*range
, *tail
;
363 /* Check whether address is unicast/broadcast or multicast */
365 address_left
= AROS_BE2LONG(*((ULONG
*)address
));
366 address_right
= AROS_BE2WORD(*((UWORD
*)(address
+ 4)));
368 if((address_left
& 0x01000000) != 0 &&
369 !(address_left
== 0xffffffff && address_right
== 0xffff))
371 /* Check if this multicast address is wanted */
373 range
= (APTR
)unit
->eu_MulticastRanges
.mlh_Head
;
374 tail
= (APTR
)&unit
->eu_MulticastRanges
.mlh_Tail
;
377 while((range
!= tail
) && !accept
)
379 if((address_left
> range
->lower_bound_left
||
380 (address_left
== range
->lower_bound_left
&&
381 address_right
>= range
->lower_bound_right
)) &&
382 (address_left
< range
->upper_bound_left
||
383 (address_left
== range
->upper_bound_left
&&
384 address_right
<= range
->upper_bound_right
)))
386 range
= (APTR
)range
->node
.mln_Succ
;
389 unit
->eu_SpecialStats
[S2SS_ETHERNET_BADMULTICAST
& 0xffff]++;
394 void rx_int(struct EMACUnit
*unit
, struct ExecBase
*SysBase
)
396 mal_descriptor_t descr
;
398 int last_slot
= unit
->eu_LastRXSlot
;
399 struct TypeStats
*tracker
;
401 struct Opener
*opener
, *opener_tail
;
402 struct IOSana2Req
*request
, *request_tail
;
403 BOOL accepted
, is_orphan
;
406 D(bug("[EMAC%d] RX Int\n", unit
->eu_UnitNum
));
407 D(bug("[EMAC%d] Starting at packet %d", unit
->eu_UnitNum
, (unit
->eu_LastRXSlot
+ 1) % RX_RING_SIZE
));
408 for (i
=1; i
<= RX_RING_SIZE
; i
++)
410 int packet_pos
= ((i
+ last_slot
) % RX_RING_SIZE
) >> 2 ;
411 int sub_pos
= ((i
+ last_slot
) % RX_RING_SIZE
) % 4;
412 mal_packet_t mal_packet
;
414 /* Invalidate each cache line - four mal descriptors at once - the very special case is
415 * the first run of interrupt handler - it has to fetch the cache line unconditionally */
416 if (!sub_pos
|| i
== 1)
418 /* Invalidate memory containing MAL descriptor */
419 CacheClearE(&unit
->eu_RXChannel
[packet_pos
], sizeof(mal_packet
), CACRF_InvalidateD
);
420 mal_packet
= unit
->eu_RXChannel
[packet_pos
];
423 /* Work on local descriptor's copy */
424 descr
= mal_packet
.descr
[sub_pos
];
426 if (!(descr
.md_ctrl
& MAL_CTRL_RX_E
))
428 struct eth_frame
*frame
;
431 unit
->eu_LastRXSlot
= (packet_pos
<< 2) + sub_pos
;
433 D(bug("[EMAC%d] MAL descriptor %d filled with %d bytes\n", unit
->eu_UnitNum
, (packet_pos
<< 2) + sub_pos
, descr
.md_length
));
435 /* Invalidate memory containing MAL descriptor */
436 CacheClearE(descr
.md_buffer
, descr
.md_length
, CACRF_InvalidateD
);
437 frame
= (struct eth_frame
*)descr
.md_buffer
;
439 /* Dump contents of frame if DEBUG enabled */
442 for (j
=0; j
<64; j
++) {
444 D(bug("\n%03x:", j
));
445 D(bug(" %02x", ((unsigned char*)frame
)[j
]));
450 /* Check for address validity */
451 if(AddressFilter(unit
->eu_EMACBase
, unit
, frame
->eth_packet_dest
))
453 /* Packet is addressed to this driver */
454 packet_type
= frame
->eth_packet_type
;
455 D(bug("[EMAC%d] Packet IP accepted with type = %d\n", unit
->eu_UnitNum
, packet_type
));
457 opener
= (APTR
)unit
->eu_Openers
.mlh_Head
;
458 opener_tail
= (APTR
)&unit
->eu_Openers
.mlh_Tail
;
459 /* Offer packet to every opener */
461 while(opener
!= opener_tail
)
463 request
= (APTR
)opener
->read_port
.mp_MsgList
.lh_Head
;
464 request_tail
= (APTR
)&opener
->read_port
.mp_MsgList
.lh_Tail
;
467 /* Offer packet to each request until it's accepted */
468 while((request
!= request_tail
) && !accepted
)
470 if((request
->ios2_PacketType
== packet_type
)
471 || ((request
->ios2_PacketType
<= ETH_MTU
)
472 && (packet_type
<= ETH_MTU
)))
474 D(bug("[EMAC%d] copy packet for opener ..\n", unit
->eu_UnitNum
));
475 CopyPacket(unit
->eu_EMACBase
, unit
, request
, descr
.md_length
, packet_type
, frame
);
479 (struct IOSana2Req
*)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
485 opener
= (APTR
)opener
->node
.mln_Succ
;
488 /* If packet was unwanted, give it to S2_READORPHAN request */
491 unit
->eu_Stats
.UnknownTypesReceived
++;
493 if(!IsMsgPortEmpty(unit
->eu_RequestPorts
[ADOPT_QUEUE
]))
495 CopyPacket(unit
->eu_EMACBase
, unit
,
496 (APTR
)unit
->eu_RequestPorts
[ADOPT_QUEUE
]->
497 mp_MsgList
.lh_Head
, descr
.md_length
, packet_type
, frame
);
498 D(bug("[EMAC%d] packet copied to orphan queue\n", unit
->eu_UnitNum
));
502 /* Update remaining statistics */
505 FindTypeStats(unit
->eu_EMACBase
, unit
, &unit
->eu_TypeTrackers
, packet_type
);
508 tracker
->stats
.PacketsReceived
++;
509 tracker
->stats
.BytesReceived
+= descr
.md_length
;
514 /* Set the descriptor back as free */
515 descr
.md_ctrl
|= MAL_CTRL_RX_E
;
518 /* Save local copy and flush data cache */
519 /* Invalidate memory containing MAL descriptor */
520 CacheClearE(&unit
->eu_RXChannel
[packet_pos
], sizeof(mal_packet
), CACRF_InvalidateD
);
521 mal_packet
= unit
->eu_RXChannel
[packet_pos
];
523 mal_packet
.descr
[sub_pos
] = descr
;
524 unit
->eu_RXChannel
[packet_pos
] = mal_packet
;
525 CacheClearE(&unit
->eu_RXChannel
[packet_pos
], sizeof(mal_packet
), CACRF_ClearD
);
530 static AROS_INTH1(EMAC_RX_Int
, struct EMACUnit
*, unit
)
534 D(bug("[EMAC%d] RX Int\n", unit
->eu_UnitNum
));
535 rx_int(unit
, SysBase
);
542 void tx_int(struct EMACUnit
*unit
, struct ExecBase
*SysBase
)
544 struct EMACBase
*EMACBase
= unit
->eu_EMACBase
;
545 mal_descriptor_t descr
;
546 int nr
, try_count
= 1;
547 int last_slot
= unit
->eu_LastTXSlot
;
548 UWORD packet_size
, data_size
;
549 struct IOSana2Req
*request
;
550 struct Opener
*opener
;
554 struct MsgPort
*port
;
555 struct TypeStats
*tracker
;
558 BOOL proceed
= TRUE
; /* Success by default */
560 port
= unit
->eu_RequestPorts
[WRITE_QUEUE
];
562 D(bug("[EMAC%d] TX Int\n", unit
->eu_UnitNum
));
563 D(bug("[EMAC%d] Starting at packet %d\d", unit
->eu_UnitNum
, (last_slot
+ 1) % TX_RING_SIZE
));
565 // for (nr=0; nr < TX_RING_SIZE; nr++)
567 // CacheClearE(&unit->eu_TXChannel[nr>>2], sizeof(mal_packet_t), CACRF_InvalidateD);
568 // D(bug("%04x ",unit->eu_TXChannel[nr>>2].descr[nr%4].md_ctrl));
570 /* Still no error and there are packets to be sent? */
571 while(proceed
&& (!IsMsgPortEmpty(port
)))
573 mal_packet_t mal_packet
;
575 nr
= (last_slot
+ 1) % TX_RING_SIZE
;
577 packet_pos
= nr
>> 2 ;
582 /* Invalidate memory containing MAL descriptor */
583 CacheClearE(&unit
->eu_TXChannel
[packet_pos
], sizeof(mal_packet
), CACRF_InvalidateD
);
584 mal_packet
= unit
->eu_TXChannel
[packet_pos
];
585 /* Work on local descriptor's copy */
586 descr
= mal_packet
.descr
[sub_pos
];
588 if (!(descr
.md_ctrl
& MAL_CTRL_TX_R
))
590 struct eth_frame
*eth
= (struct eth_frame
*)descr
.md_buffer
;
591 request
= (APTR
)port
->mp_MsgList
.lh_Head
;
592 data_size
= packet_size
= request
->ios2_DataLength
;
594 opener
= (APTR
)request
->ios2_BufferManagement
;
596 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
598 packet_size
+= ETH_PACKET_DATA
;
599 CopyMem(request
->ios2_DstAddr
, eth
->eth_packet_dest
, ETH_ADDRESSSIZE
);
600 CopyMem(unit
->eu_DevAddr
, eth
->eth_packet_source
, ETH_ADDRESSSIZE
);
601 eth
->eth_packet_type
= request
->ios2_PacketType
;
603 buffer
= eth
->eth_packet_data
;
606 buffer
= descr
.md_buffer
;
608 if (!opener
->tx_function(buffer
, request
->ios2_Data
, data_size
))
610 error
= S2ERR_NO_RESOURCES
;
611 wire_error
= S2WERR_BUFF_ERROR
;
612 ReportEvents(EMACBase
, unit
,
613 S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
619 D(bug("[EMAC%d] packet %d:%d [type = %d] queued for transmission.", unit
->eu_UnitNum
, last_slot
, nr
, eth
->eth_packet_type
));
621 /* Dump contents of frame if DEBUG enabled */
624 for (j
=0; j
<64; j
++) {
626 D(bug("\n%03x:", j
));
627 D(bug(" %02x", ((unsigned char*)eth
)[j
]));
632 /* Update the descriptor */
633 descr
.md_length
= packet_size
;
634 descr
.md_ctrl
|= MAL_CTRL_TX_R
| MAL_CTRL_TX_I
| MAL_CTRL_TX_L
| EMAC_CTRL_TX_GFCS
| EMAC_CTRL_TX_GP
;
635 CacheClearE(descr
.md_buffer
, descr
.md_length
, CACRF_ClearD
);
637 CacheClearE(&unit
->eu_TXChannel
[packet_pos
], sizeof(mal_packet
), CACRF_InvalidateD
);
638 mal_packet
= unit
->eu_TXChannel
[packet_pos
];
639 mal_packet
.descr
[sub_pos
] = descr
;
640 unit
->eu_TXChannel
[packet_pos
] = mal_packet
;
641 CacheClearE(&unit
->eu_TXChannel
[packet_pos
], sizeof(mal_packet
), CACRF_ClearD
);
646 request
->ios2_Req
.io_Error
= error
;
647 request
->ios2_WireError
= wire_error
;
649 Remove((APTR
)request
);
651 ReplyMsg((APTR
)request
);
653 /* Update statistics */
657 tracker
= FindTypeStats(EMACBase
, unit
, &unit
->eu_TypeTrackers
,
658 request
->ios2_PacketType
);
661 tracker
->stats
.PacketsSent
++;
662 tracker
->stats
.BytesSent
+= packet_size
;
668 unit
->eu_LastTXSlot
= ++last_slot
;
672 * If we've just run out of free space on the TX queue, stop
673 * it and give up pushing further frames
675 if ( (try_count
+ 1) >= TX_RING_SIZE
)
677 D(bug("[EMAC%d] output queue full!. Stopping [count = %d, TX_RING_SIZE = %d\n", unit
->eu_UnitNum
, try_count
, TX_RING_SIZE
));
682 /* Tell EMAC that it has new packets to process */
683 outl(inl(EMAC_TXM0
+ unit
->eu_IOBase
) | EMAC_TXM0_GNP0
, EMAC_TXM0
+ unit
->eu_IOBase
);
685 /* Was there success? Enable incomming of new packets */
687 unit
->eu_RequestPorts
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
689 unit
->eu_RequestPorts
[WRITE_QUEUE
]->mp_Flags
= PA_IGNORE
;
693 static AROS_INTH1(EMAC_TX_Int
, struct EMACUnit
*, unit
)
697 D(bug("[EMAC%d] TX Int\n", unit
->eu_UnitNum
));
698 tx_int(unit
, SysBase
);
705 static AROS_INTH1(EMAC_TXEnd_Int
, struct EMACUnit
*, unit
)
709 D(bug("[EMAC%d] TX End Int\n", unit
->eu_UnitNum
));
716 struct TypeStats
*FindTypeStats(struct EMACBase
*EMACBase
, struct EMACUnit
*unit
,
717 struct MinList
*list
, ULONG packet_type
)
719 struct TypeStats
*stats
, *tail
;
722 stats
= (APTR
)list
->mlh_Head
;
723 tail
= (APTR
)&list
->mlh_Tail
;
725 while(stats
!= tail
&& !found
)
727 if(stats
->packet_type
== packet_type
)
730 stats
= (APTR
)stats
->node
.mln_Succ
;
740 AROS_UFH3(void, EMAC_UnitProcess
,
741 AROS_UFHA(char *, argPtr
, A0
),
742 AROS_UFHA(ULONG
, argSize
, D0
),
743 AROS_UFHA(struct ExecBase
*, SysBase
, A6
))
747 struct MsgPort
*iport
;
748 struct EMACUnit
*unit
= (struct EMACUnit
*)(FindTask(NULL
)->tc_UserData
);
749 struct Process
*parent
= unit
->eu_Process
;
751 unit
->eu_Process
= (struct Process
*)FindTask(NULL
);
753 D(bug("[EMAC%d] Hello there.\n", unit
->eu_UnitNum
));
754 D(bug("[EMAC%d] Process @ %p\n", unit
->eu_UnitNum
, unit
->eu_Process
));
757 unit
->eu_OpenCount
= 0;
758 unit
->eu_RangeCount
= 0;
760 iport
= CreateMsgPort();
762 unit
->eu_InputPort
= iport
;
764 unit
->eu_TimerPort
.mp_SigBit
= SIGB_SINGLE
;
765 unit
->eu_TimerPort
.mp_Flags
= PA_SIGNAL
;
766 unit
->eu_TimerPort
.mp_SigTask
= FindTask(NULL
);
767 unit
->eu_TimerPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
768 NEWLIST(&unit
->eu_TimerPort
.mp_MsgList
);
770 unit
->eu_TimerRequest
.tr_node
.io_Message
.mn_ReplyPort
= &unit
->eu_TimerPort
;
771 unit
->eu_TimerRequest
.tr_node
.io_Message
.mn_Length
= sizeof(unit
->eu_TimerRequest
);
773 OpenDevice((STRPTR
)"timer.device", UNIT_MICROHZ
, (struct IORequest
*)&unit
->eu_TimerRequest
, 0);
777 Signal((struct Task
*)parent
, SIGF_SINGLE
);
780 uint32_t sigset
= 1 << iport
->mp_SigBit
|
783 uint32_t rcvd
= Wait(sigset
);
785 if (rcvd
& SIGBREAKF_CTRL_C
)
787 D(bug("[EMAC%d] CTRL_C signal\n", unit
->eu_UnitNum
));
789 else if (rcvd
& (1 << iport
->mp_SigBit
))
791 struct IOSana2Req
*io
;
793 /* Handle incoming transactions */
794 while ((io
= (struct IOSana2Req
*)GetMsg(iport
)) != NULL
)
796 D(bug("[EMAC%d] Handle incomming transaction.\n", unit
->eu_UnitNum
));
797 ObtainSemaphore(&unit
->eu_Lock
);
798 handle_request(unit
->eu_EMACBase
, io
);
807 static const struct UnitInfo
{
812 } EMAC_Units_sam440
[2] = {
813 { INTR_ETH0
, EMAC_TASK1_NAME
, EMAC0_BASE
, 24 },
814 { INTR_ETH1
, EMAC_TASK2_NAME
, EMAC1_BASE
, 25 },
815 }, EMAC_Units_sam460
[2] = {
816 { INTR_UIC2_BASE
+ INTR_UIC2_EMAC0
, EMAC_TASK1_NAME
, EMAC0_BASE
, 0 },
817 { INTR_UIC2_BASE
+ INTR_UIC2_EMAC0
, EMAC_TASK2_NAME
, EMAC1_BASE
, 1 },
822 struct Library
*ProcessorBase
= OpenResource(PROCESSORNAME
);
826 struct TagItem tags
[] = {
827 { GCIT_Model
, (IPTR
)&pvr
},
836 struct EMACUnit
*CreateUnit(struct EMACBase
*EMACBase
, uint8_t num
)
838 void *KernelBase
= OpenResource("kernel.resource");
840 D(bug("[EMAC ] CreateUnit(%d)\n", num
));
842 struct EMACUnit
*unit
= AllocPooled(EMACBase
->emb_Pool
, sizeof(struct EMACUnit
));
847 const struct UnitInfo
*EMAC_Units
;
849 if (GetPVR() == PVR_PPC460EX_B
) {
850 EMAC_Units
= &EMAC_Units_sam460
[0];
852 EMAC_Units
= &EMAC_Units_sam440
[0];
855 InitSemaphore(&unit
->eu_Lock
);
857 NEWLIST(&unit
->eu_Openers
);
858 NEWLIST(&unit
->eu_MulticastRanges
);
859 NEWLIST(&unit
->eu_TypeTrackers
);
861 unit
->eu_UnitNum
= num
;
862 unit
->eu_IRQHandler
= KrnAddIRQHandler(EMAC_Units
[num
].ui_IrqNum
, EMACIRQHandler
, EMACBase
, unit
);
863 unit
->eu_EMACBase
= EMACBase
;
864 unit
->eu_IOBase
= EMAC_Units
[num
].ui_IOBase
;
865 unit
->eu_PHYAddr
= EMAC_Units
[num
].ui_PHYAddr
;
866 unit
->eu_MTU
= ETH_MTU
;
868 unit
->eu_LastTXSlot
= TX_RING_SIZE
- 1;
869 unit
->eu_LastRXSlot
= RX_RING_SIZE
- 1;
871 unit
->start
= EMAC_Start
;
872 unit
->stop
= EMAC_Stop
;
873 unit
->set_mac_address
= EMAC_SetMacAddress
;
874 unit
->udelay
= EMAC_UDelay
;
876 unit
->eu_RXInt
.is_Node
.ln_Name
= "EMAC RX Int";
877 unit
->eu_RXInt
.is_Code
= (VOID_FUNC
)EMAC_RX_Int
;
878 unit
->eu_RXInt
.is_Data
= unit
;
880 unit
->eu_TXInt
.is_Node
.ln_Name
= "EMAC TX Int";
881 unit
->eu_TXInt
.is_Code
= (VOID_FUNC
)EMAC_TX_Int
;
882 unit
->eu_TXInt
.is_Data
= unit
;
884 unit
->eu_TXEndInt
.is_Node
.ln_Name
= "EMAC TX Int";
885 unit
->eu_TXEndInt
.is_Code
= (VOID_FUNC
)EMAC_TXEnd_Int
;
886 unit
->eu_TXEndInt
.is_Data
= unit
;
888 unit
->eu_RXChannel
= (mal_packet_t
*)EMACBase
->emb_MALRXChannels
[num
];
889 unit
->eu_TXChannel
= (mal_packet_t
*)EMACBase
->emb_MALTXChannels
[num
];
890 //unit->eu_TXChannel[1] = (mal_packet_t *)EMACBase->emb_MALTXChannels[2*num+1];
892 for (i
=0; i
< REQUEST_QUEUE_COUNT
; i
++)
894 struct MsgPort
*port
= AllocPooled(EMACBase
->emb_Pool
, sizeof(struct MsgPort
));
895 unit
->eu_RequestPorts
[i
] = port
;
899 NEWLIST(&port
->mp_MsgList
);
900 port
->mp_Flags
= PA_IGNORE
;
901 port
->mp_SigTask
= &unit
->eu_TXInt
;
905 unit
->eu_RequestPorts
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
907 /* Create the unit's process */
909 /* Unit's process pointer will temporarly contain the parent */
910 unit
->eu_Process
= (struct Process
*)FindTask(NULL
);
912 NP_Entry
, (IPTR
)EMAC_UnitProcess
,
913 NP_Name
, EMAC_Units
[num
].ui_TaskName
,
915 NP_UserData
, (IPTR
)unit
,
919 /* Wait for synchronisation signal */
922 D(bug("[EMAC ] Unit %d up and running\n", num
));
928 static struct AddressRange
*FindMulticastRange(struct EMACBase
*EMACBase
, struct EMACUnit
*unit
,
929 ULONG lower_bound_left
, UWORD lower_bound_right
, ULONG upper_bound_left
, UWORD upper_bound_right
)
931 struct AddressRange
*range
, *tail
;
934 range
= (APTR
)unit
->eu_MulticastRanges
.mlh_Head
;
935 tail
= (APTR
)&unit
->eu_MulticastRanges
.mlh_Tail
;
937 while((range
!= tail
) && !found
)
939 if((lower_bound_left
== range
->lower_bound_left
) &&
940 (lower_bound_right
== range
->lower_bound_right
) &&
941 (upper_bound_left
== range
->upper_bound_left
) &&
942 (upper_bound_right
== range
->upper_bound_right
))
945 range
= (APTR
)range
->node
.mln_Succ
;
954 BOOL
AddMulticastRange(struct EMACBase
*EMACBase
, struct EMACUnit
*unit
, const UBYTE
*lower_bound
, const UBYTE
*upper_bound
)
956 struct AddressRange
*range
;
957 ULONG lower_bound_left
, upper_bound_left
;
958 UWORD lower_bound_right
, upper_bound_right
;
960 lower_bound_left
= AROS_BE2LONG(*((ULONG
*)lower_bound
));
961 lower_bound_right
= AROS_BE2WORD(*((UWORD
*)(lower_bound
+ 4)));
962 upper_bound_left
= AROS_BE2LONG(*((ULONG
*)upper_bound
));
963 upper_bound_right
= AROS_BE2WORD(*((UWORD
*)(upper_bound
+ 4)));
965 range
= FindMulticastRange(EMACBase
, unit
, lower_bound_left
, lower_bound_right
,
966 upper_bound_left
, upper_bound_right
);
972 range
= AllocPooled(EMACBase
->emb_Pool
, sizeof(struct AddressRange
));
975 range
->lower_bound_left
= lower_bound_left
;
976 range
->lower_bound_right
= lower_bound_right
;
977 range
->upper_bound_left
= upper_bound_left
;
978 range
->upper_bound_right
= upper_bound_right
;
979 range
->add_count
= 1;
982 AddTail((APTR
)&unit
->eu_MulticastRanges
, (APTR
)range
);
985 if (unit
->eu_RangeCount
++ == 0)
987 unit
->eu_Flags
|= IFF_ALLMULTI
;
988 unit
->set_multicast(unit
);
993 return range
!= NULL
;
996 BOOL
RemMulticastRange(struct EMACBase
*EMACBase
, struct EMACUnit
*unit
, const UBYTE
*lower_bound
, const UBYTE
*upper_bound
)
998 struct AddressRange
*range
;
999 ULONG lower_bound_left
, upper_bound_left
;
1000 UWORD lower_bound_right
, upper_bound_right
;
1002 lower_bound_left
= AROS_BE2LONG(*((ULONG
*)lower_bound
));
1003 lower_bound_right
= AROS_BE2WORD(*((UWORD
*)(lower_bound
+ 4)));
1004 upper_bound_left
= AROS_BE2LONG(*((ULONG
*)upper_bound
));
1005 upper_bound_right
= AROS_BE2WORD(*((UWORD
*)(upper_bound
+ 4)));
1007 range
= FindMulticastRange(EMACBase
, unit
, lower_bound_left
, lower_bound_right
,
1008 upper_bound_left
, upper_bound_right
);
1012 if(--range
->add_count
== 0)
1015 Remove((APTR
)range
);
1017 FreePooled(EMACBase
->emb_Pool
, range
, sizeof(struct AddressRange
));
1019 if (--unit
->eu_RangeCount
== 0)
1021 unit
->eu_Flags
&= ~IFF_ALLMULTI
;
1022 unit
->set_multicast(unit
);
1026 return range
!= NULL
;