6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
22 #include <exec/types.h>
23 #include <exec/resident.h>
25 #include <exec/ports.h>
26 #include <exec/errors.h>
30 #include <devices/sana2.h>
31 #include <devices/sana2specialstats.h>
32 #include <devices/newstyle.h>
33 #include <devices/timer.h>
35 #include <utility/utility.h>
36 #include <utility/tagitem.h>
37 #include <utility/hooks.h>
39 #include <proto/exec.h>
40 #include <proto/dos.h>
41 #include <proto/oop.h>
42 #include <proto/timer.h>
43 #include <proto/utility.h>
50 #include LC_LIBDEFS_FILE
52 extern UBYTE
MMIO_R8(UBYTE
*);
53 extern UWORD
MMIO_R16(UWORD
*);
54 extern ULONG
MMIO_R32(ULONG
*);
56 extern void rtl8169_CheckLinkStatus(struct net_device
*);
59 * Report incoming events to all hyphotetical event receivers
61 VOID
ReportEvents(struct RTL8169Base
*RTL8169DeviceBase
, struct RTL8169Unit
*unit
, ULONG events
)
63 struct IOSana2Req
*request
, *tail
, *next_request
;
66 list
= &unit
->rtl8169u_request_ports
[EVENT_QUEUE
]->mp_MsgList
;
67 next_request
= (APTR
)list
->lh_Head
;
68 tail
= (APTR
)&list
->lh_Tail
;
70 /* Go through list of event listeners. If send messages to receivers if event found */
72 while(next_request
!= tail
)
74 request
= next_request
;
75 next_request
= (APTR
)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
77 if((request
->ios2_WireError
&events
) != 0)
79 request
->ios2_WireError
= events
;
80 Remove((APTR
) request
);
81 ReplyMsg((APTR
) request
);
87 struct TypeStats
*FindTypeStats(struct RTL8169Base
*RTL8169DeviceBase
, struct RTL8169Unit
*unit
,
88 struct MinList
*list
, ULONG packet_type
)
90 struct TypeStats
*stats
, *tail
;
93 stats
= (APTR
)list
->mlh_Head
;
94 tail
= (APTR
)&list
->mlh_Tail
;
96 while(stats
!= tail
&& !found
)
98 if(stats
->packet_type
== packet_type
)
104 stats
= (APTR
) stats
->node
.mln_Succ
;
116 void FlushUnit(LIBBASETYPEPTR LIBBASE
, struct RTL8169Unit
*unit
, UBYTE last_queue
, BYTE error
)
118 struct IORequest
*request
;
120 struct Opener
*opener
, *tail
;
122 RTLD(bug("[%s] unit.FlushUnit\n", unit
->rtl8169u_name
))
124 /* Abort queued operations */
125 for (i
=0; i
<= last_queue
; i
++)
127 while ((request
= (APTR
) GetMsg(unit
->rtl8169u_request_ports
[i
])) != NULL
)
129 request
->io_Error
= IOERR_ABORTED
;
130 ReplyMsg((struct Message
*)request
);
134 opener
= (APTR
) unit
->rtl8169u_Openers
.mlh_Head
;
135 tail
= (APTR
) unit
->rtl8169u_Openers
.mlh_Tail
;
137 /* Flush every opener's read queue */
138 while(opener
!= tail
)
140 while ((request
= (APTR
) GetMsg(&opener
->read_port
)) != NULL
)
142 request
->io_Error
= error
;
143 ReplyMsg((struct Message
*) request
);
145 opener
= (struct Opener
*)opener
->node
.mln_Succ
;
149 static inline int rtl8169_fragmented_frame(ULONG status
)
151 return (status
& (FirstFrag
| LastFrag
)) != (FirstFrag
| LastFrag
);
154 static inline void rtl8169_MarkToASIC(struct RxDesc
*desc
, ULONG rx_buf_sz
)
156 // ULONG eor = AROS_LE2LONG(desc->opts1) & RingEnd;
158 desc
->opts1
= AROS_LONG2LE(DescOwn
| rx_buf_sz
);
161 /* Interrupt Rx Support Function ..
162 * It's duty is to iterate through RX queue searching for new packets.
164 void RTL8169_Rx_Process(struct RTL8169Unit
*unit
)
166 struct RTL8169Base
*RTL8169DeviceBase
= unit
->rtl8169u_device
;
167 struct rtl8169_priv
*np
= unit
->rtl8169u_priv
;
168 // UBYTE *base = unit->rtl8169u_BaseMem;
170 struct TypeStats
*tracker
;
172 struct Opener
*opener
;
173 struct Opener
*opener_tail
;
174 struct IOSana2Req
*request
;
175 struct IOSana2Req
*request_tail
;
178 // unsigned int delta;
179 // unsigned int count;
180 // unsigned int rx_left;
183 RTLD(bug("[%s] RTL8169_Rx_Process()\n", unit
->rtl8169u_name
))
188 // UWORD overspill = 0;
189 struct eth_frame
*frame
;
191 unsigned long rx_status
;
192 unsigned int rx_size
;
195 struct RxDesc
*desc
= np
->RxDescArray
+ cur_rx
;
197 rx_status
= AROS_LE2LONG(desc
->opts1
);
199 if(rx_status
& DescOwn
)
204 rx_size
= (rx_status
& 0x00001FFF) - ETH_CRCSIZE
;
206 if (rx_status
& RxRES
)
208 RTLD(bug("[%s] RTL8169_RX_Process: Ethernet frame had errors, Status %8.8x\n",
209 unit
->rtl8169u_name
, rx_status
))
210 rtl8169_MarkToASIC(desc
, (ULONG
) np
->rx_buf_sz
);
215 frame
= (APTR
)(IPTR
)AROS_LE2LONG(desc
->addr
);
217 RTLD(bug("[%s] RTL8169_RX_Process: frame @ %p, len=%d, pool index=%d\n", unit
->rtl8169u_name
, frame
, len
, cur_rx
))
219 // got a valid packet - forward it to the network core
222 // Check for address validity
223 if(AddressFilter(LIBBASE
, unit
, frame
->eth_packet_dest
))
225 // Packet is addressed to this driver
226 packet_type
= AROS_BE2WORD(frame
->eth_packet_type
);
227 RTLD(bug("[%s] RTL8169_RX_Process: Packet IP accepted with type = %d\n",
228 unit
->rtl8169u_name
, packet_type
))
230 opener
= (APTR
) unit
->rtl8169u_Openers
.mlh_Head
;
231 opener_tail
= (APTR
) &unit
->rtl8169u_Openers
.mlh_Tail
;
233 // Offer packet to every opener
234 while(opener
!= opener_tail
)
236 RTLD(bug("[%s] RTL8169_RX_Process: checking opener %p\n", unit
->rtl8169u_name
, opener
))
238 request
= (APTR
) opener
->read_port
.mp_MsgList
.lh_Head
;
239 request_tail
= (APTR
) &opener
->read_port
.mp_MsgList
.lh_Tail
;
242 // Offer packet to each request until it's accepted
243 while((request
!= request_tail
) && !accepted
)
245 if((request
->ios2_PacketType
== packet_type
)
246 || ((request
->ios2_PacketType
<= ETH_MTU
)
247 && (packet_type
<= ETH_MTU
)))
249 RTLD(bug("[%s] RTL8169_RX_Process: copy packet for opener ...\n", unit
->rtl8169u_name
))
250 CopyPacket(LIBBASE
, unit
, request
, len
, packet_type
, frame
);
253 request
= (struct IOSana2Req
*) request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
261 opener
= (APTR
) opener
->node
.mln_Succ
;
264 // If packet was unwanted, give it to S2_READORPHAN request
267 unit
->rtl8169u_stats
.UnknownTypesReceived
++;
269 if(!IsMsgPortEmpty(unit
->rtl8169u_request_ports
[ADOPT_QUEUE
]))
271 RTLD(bug("[%s] RTL8169_RX_Process: copy orphan packet ...\n", unit
->rtl8169u_name
))
272 CopyPacket(LIBBASE
, unit
,
273 (APTR
) unit
->rtl8169u_request_ports
[ADOPT_QUEUE
]->mp_MsgList
.lh_Head
,
278 RTLD(bug("[%s] RTL8169_RX_Process: packet copied to orphan queue\n", unit
->rtl8169u_name
))
282 rtl8169_MarkToASIC(desc
, (ULONG
) np
->rx_buf_sz
);
284 // Update remaining statistics
285 tracker
= FindTypeStats(LIBBASE
, unit
, &unit
->rtl8169u_type_trackers
, packet_type
);
289 tracker
->stats
.PacketsReceived
++;
290 tracker
->stats
.BytesReceived
+= len
;
291 RTLD(bug("[%s] RTL8169_RX_Process: stats updated.\n", unit
->rtl8169u_name
))
294 unit
->rtl8169u_stats
.PacketsReceived
++;
297 /* if((desc->opts2 & AROS_LONG2LE(0xfffe000) &&
298 np->mcfg == RTL_GIGA_MAC_VER_05))
304 if(np
->cur_rx
== (NUM_RX_DESC
- 1))
306 desc
->opts1
= AROS_LONG2LE((DescOwn
| RingEnd
| (ULONG
) np
->rx_buf_sz
));
311 desc
->opts1
= AROS_LONG2LE(DescOwn
| (ULONG
) np
->rx_buf_sz
);
316 np
->cur_rx
%= NUM_RX_DESC
;
318 // if(np->cur_rx >= NUM_RX_DESC)
320 // RTLD(bug("[%s] RTL8169_RX_Process: rx buffers pool exhausted.\n", unit->rtl8169u_name))
327 * Interrupt generated by Cause() to push new packets into the NIC interface
329 static AROS_INTH1(RTL8169_TX_IntF
, struct RTL8169Unit
*, unit
)
333 struct rtl8169_priv
*np
= unit
->rtl8169u_priv
;
334 struct RTL8169Base
*RTL8169DeviceBase
= unit
->rtl8169u_device
;
336 BOOL proceed
= FALSE
; /* Fails by default */
338 RTLD(bug("[%s] RTL8169_TX_IntF()\n", unit
->rtl8169u_name
))
340 // send packet only if there is free space on tx queue. Otherwise do nothing
341 if (!netif_queue_stopped(unit
))
343 UWORD packet_size
, data_size
;
344 struct IOSana2Req
*request
;
345 struct Opener
*opener
;
347 ULONG wire_error
= 0;
349 struct MsgPort
*port
;
350 struct TypeStats
*tracker
;
352 proceed
= TRUE
; // Success by default
353 UBYTE
*base
= (UBYTE
*) unit
->rtl8169u_BaseMem
;
354 port
= unit
->rtl8169u_request_ports
[WRITE_QUEUE
];
356 // Still no error and there are packets to be sent ?
357 while(!IsMsgPortEmpty(port
))
359 nr
= np
->cur_tx
% NUM_TX_DESC
;
362 request
= (APTR
) port
->mp_MsgList
.lh_Head
;
363 data_size
= packet_size
= request
->ios2_DataLength
;
365 opener
= (APTR
) request
->ios2_BufferManagement
;
367 if (!(AROS_LE2LONG(np
->TxDescArray
[nr
].opts1
) & DescOwn
))
369 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
371 packet_size
+= ETH_PACKET_DATA
;
372 CopyMem(request
->ios2_DstAddr
,
373 &((struct eth_frame
*)(IPTR
)np
->TxDescArray
[nr
].addr
)->eth_packet_dest
,
375 CopyMem(unit
->rtl8169u_dev_addr
,
376 &((struct eth_frame
*)(IPTR
)np
->TxDescArray
[nr
].addr
)->eth_packet_source
,
378 ((struct eth_frame
*)(IPTR
)np
->TxDescArray
[nr
].addr
)->eth_packet_type
= AROS_WORD2BE(request
->ios2_PacketType
);
380 buffer
= (APTR
)&((struct eth_frame
*)(IPTR
)np
->TxDescArray
[nr
].addr
)->eth_packet_data
;
384 buffer
= (APTR
)(IPTR
)np
->TxDescArray
[nr
].addr
;
386 if (packet_size
< TX_BUF_SIZE
)
388 memset(buffer
, 0, TX_BUF_SIZE
- packet_size
);
391 if (!opener
->tx_function(buffer
, request
->ios2_Data
, data_size
))
393 error
= S2ERR_NO_RESOURCES
;
394 wire_error
= S2WERR_BUFF_ERROR
;
395 ReportEvents(LIBBASE
, unit
,
396 S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
|
400 // Now the packet is already in TX buffer, update flags for NIC
405 RTLD(bug("[%s] RTL8139_TX_IntF: packet %d @ %p [type = %d] queued for transmission.",
408 (APTR
)(IPTR
)np
->TxDescArray
[nr
].addr
,
409 AROS_BE2WORD(((struct eth_frame
*)(IPTR
)np
->TxDescArray
[nr
].addr
)->eth_packet_type
)))
412 for (j
= 0; j
< 64; j
++)
418 bug(" %02x", ((unsigned char*)(IPTR
)np
->TxDescArray
[nr
].addr
)[j
]);
425 // Set the ring details for the packet ..
426 np
->TxDescArray
[nr
].opts1
= AROS_LONG2LE(DescOwn
| FirstFrag
| LastFrag
| packet_size
| (RingEnd
* !((nr
+ 1) % NUM_TX_DESC
)));
427 np
->TxDescArray
[nr
].opts2
= AROS_LONG2LE(0);
429 RTL_W8(base
+ (TxPoll
), NPQ
);
433 request
->ios2_Req
.io_Error
= error
;
434 request
->ios2_WireError
= wire_error
;
436 Remove((APTR
) request
);
438 ReplyMsg((APTR
) request
);
443 tracker
= FindTypeStats(LIBBASE
, unit
,
444 &unit
->rtl8169u_type_trackers
,
445 request
->ios2_PacketType
);
448 tracker
->stats
.PacketsSent
++;
449 tracker
->stats
.BytesSent
+= packet_size
;
458 // Was there success? Enable incoming of new packets
461 unit
->rtl8169u_request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
465 unit
->rtl8169u_request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_IGNORE
;
474 * Handle timeouts and other strange cases
476 static AROS_INTH1(RTL8169_TimeoutHandlerF
, struct RTL8169Unit
*,unit
)
481 struct Device
*TimerBase
= unit
->rtl8169u_TimerSlowReq
->tr_node
.io_Device
;
484 //RTLD(bug("[%s] RTL8169_TimeoutHandlerF()\n", unit->rtl8169u_name))
487 * If timeout timer is expected, and time elapsed - regenerate the
490 if (unit
->rtl8169u_toutNEED
&& (CmpTime(&time
, &unit
->rtl8169u_toutPOLL
) < 0))
492 unit
->rtl8169u_toutNEED
= FALSE
;
493 //Cause(&unit->rtl8169u_tx_end_int);
501 /*static void RTL8169_Tx_Cleanup(struct net_device *unit)
503 struct rtl8169_priv *np = unit->rtl8169u_priv;
504 unsigned int dirty_tx, tx_left;
505 struct TypeStats *tracker;
507 dirty_tx = np->dirty_tx;
508 tx_left = np->cur_tx - dirty_tx;
512 unsigned int entry = dirty_tx % NUM_TX_DESC;
513 ULONG packet_size, status;
515 status = AROS_LE2LONG(np->TxDescArray[entry].opts1);
517 if (status & DescOwn)
522 packet_size = status & 0x3FFF;
523 tracker = FindTypeStats(unit->rtl8169u_device,
525 &unit->rtl8169u_type_trackers,
526 ((struct eth_frame *) np->TxDescArray[entry].addr)->eth_packet_type);
529 tracker->stats.PacketsSent++;
530 tracker->stats.BytesSent += packet_size;
533 if (status & LastFrag)
535 RTLD(bug("[%s] RTL8169_Tx_Cleanup: Released buffer %d (%d bytes)\n", unit->rtl8169u_name, entry, packet_size))
536 np->TxDescArray[entry].opts1 = AROS_LONG2LE(RingEnd);
537 np->TxDescArray[entry].addr = NULL;
542 if (np->dirty_tx != dirty_tx)
544 np->dirty_tx = dirty_tx;
549 * Interrupt handler called whenever RTL8169 NIC interface generates interrupt.
551 static AROS_INTH1(RTL8169_IntHandlerF
, struct RTL8169Unit
*, unit
)
555 struct rtl8169_priv
*np
= unit
->rtl8169u_priv
;
556 UBYTE
*base
= (UBYTE
*) unit
->rtl8169u_BaseMem
;
559 int boguscnt
= unit
->rtl8169u_device
->rtl8169b_MaxIntWork
;
561 np
->intr_mask
= 0xffff;
563 RTL_W16(base
+ (IntrMask
), 0x0000);
567 status
= RTL_R16(base
+ (IntrStatus
));
569 RTLD(bug("[%s] RTL8169_IntHandlerF(), Status: %x\n", unit
->rtl8169u_name
, status
))
571 /* hotplug/major error/no more work/shared irq */
572 if ((status
== 0xFFFF) || !status
)
577 status
&= np
->intr_mask
;
578 RTL_W16(base
+ (IntrStatus
), (status
& RxFIFOOver
) ? (status
| RxOverflow
) : status
);
580 if (!(status
& np
->intr_event
))
585 /* Work around for rx fifo overflow */
586 if ((status
& RxFIFOOver
) &&
587 (np
->mcfg
== RTL_GIGA_MAC_VER_11
))
589 RTL_W16(base
+ (IntrStatus
), RxFIFOOver
);
590 RTLD(bug("[%s] RTL8169_IntHandlerF: Rx FIFO overflow occured!\n", unit
->rtl8169u_name
))
596 RTLD(bug("[%s] RTL8169_IntHandlerF: PCI error occured!\n", unit
->rtl8169u_name
))
600 if (status
& LinkChg
)
602 RTLD(bug("[%s] RTL8169_IntHandlerF: Link Change!\n", unit
->rtl8169u_name
))
603 rtl8169_CheckLinkStatus(unit
);
606 if ((status
& TxOK
) && (status
& TxDescUnavail
))
608 RTL_W8(base
+ (TxPoll
), NPQ
);
609 RTL_W16(base
+ (IntrStatus
), TxDescUnavail
);
612 if(status
& (RxOK
| RxFIFOOver
))
614 RTL8169_Rx_Process(unit
);
617 // if (status & (TxOK | TxErr))
619 // RTL8169_Tx_Cleanup(unit);
622 /* if (status & np->napi_event)
624 RTLD(bug("[%s] RTL8169_IntHandlerF: napi event!\n", unit->rtl8169u_name))
625 RTL_W16(base + IntrMask, np->intr_event & ~np->napi_event);
626 // np->intr_mask = ~np->napi_event;
630 } while (boguscnt
> 0);
634 RTLD(bug("[%s] RTL8169_IntHandlerF: Too much work in interrupt!\n", unit
->rtl8169u_name
))
635 // Clear all interrupt sources.
636 RTL_W16(base
+ (IntrStatus
), 0xffff);
639 RTL_W16(base
+ (IntrMask
), np
->intr_mask
);
646 int CopyPacket(struct RTL8169Base
*RTL8169DeviceBase
, struct RTL8169Unit
*unit
,
647 struct IOSana2Req
*request
, UWORD packet_size
, UWORD packet_type
,
648 struct eth_frame
*buffer
)
650 struct Opener
*opener
;
651 BOOL filtered
= FALSE
;
653 const UBYTE broadcast
[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
655 RTLD(bug("[%s] CopyPacket(packet @ %x, len = %d)\n", unit
->rtl8169u_name
, buffer
, packet_size
))
657 /* Set multicast and broadcast flags */
659 request
->ios2_Req
.io_Flags
&= ~(SANA2IOF_BCAST
| SANA2IOF_MCAST
);
660 if (memcmp(buffer
->eth_packet_dest
, broadcast
, 6) == 0)
662 request
->ios2_Req
.io_Flags
|= SANA2IOF_BCAST
;
663 RTLD(bug("[%s] CopyPacket: BROADCAST Flag set\n", unit
->rtl8169u_name
))
665 else if((buffer
->eth_packet_dest
[0] & 0x1) != 0)
667 request
->ios2_Req
.io_Flags
|= SANA2IOF_MCAST
;
668 RTLD(bug("[%s] CopyPacket: MULTICAST Flag set\n", unit
->rtl8169u_name
))
671 /* Set source and destination addresses and packet type */
672 RTLD(bug("[%s] Copymem... @ %x\n", unit
->rtl8169u_name
, buffer
))
673 CopyMem(buffer
->eth_packet_source
, request
->ios2_SrcAddr
, ETH_ADDRESSSIZE
);
674 CopyMem(buffer
->eth_packet_dest
, request
->ios2_DstAddr
, ETH_ADDRESSSIZE
);
675 request
->ios2_PacketType
= packet_type
;
677 /* Adjust for cooked packet request */
679 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
681 packet_size
-= ETH_PACKET_DATA
;
682 ptr
= (UBYTE
*) &buffer
->eth_packet_data
[0];
686 ptr
= (UBYTE
*) buffer
;
689 request
->ios2_DataLength
= packet_size
;
691 RTLD(bug("[%s] CopyPacket: packet @ %x (%d bytes)\n", unit
->rtl8169u_name
, ptr
, packet_size
))
694 opener
= request
->ios2_BufferManagement
;
695 if((request
->ios2_Req
.io_Command
== CMD_READ
) &&
696 (opener
->filter_hook
!= NULL
))
698 if(!CallHookPkt(opener
->filter_hook
, request
, ptr
))
700 RTLD(bug("[%s] CopyPacket: packet filtered\n", unit
->rtl8169u_name
))
707 /* Copy packet into opener's buffer and reply packet */
708 RTLD(bug("[%s] CopyPacket: opener receive packet ... ", unit
->rtl8169u_name
))
709 if(!opener
->rx_function(request
->ios2_Data
, ptr
, packet_size
))
711 RTLD(bug("ERROR occured!!\n"))
712 request
->ios2_Req
.io_Error
= S2ERR_NO_RESOURCES
;
713 request
->ios2_WireError
= S2WERR_BUFF_ERROR
;
714 ReportEvents(LIBBASE
, unit
, S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
| S2EVENT_RX
);
718 RTLD(bug("SUCCESS!!\n"))
721 Remove((APTR
) request
);
723 ReplyMsg((APTR
) request
);
724 RTLD(bug("[%s] CopyPacket: opener notified.\n", unit
->rtl8169u_name
))
730 BOOL
AddressFilter(struct RTL8169Base
*RTL8169DeviceBase
, struct RTL8169Unit
*unit
, UBYTE
*address
)
732 struct AddressRange
*range
, *tail
;
737 /* Check whether address is unicast/broadcast or multicast */
739 RTLD(bug("[%s] AddressFilter()\n", unit
->rtl8169u_name
))
741 address_left
= AROS_BE2LONG(*((ULONG
*) address
));
742 address_right
= AROS_BE2WORD(*((UWORD
*) (address
+ 4)));
744 if((address_left
& 0x01000000) != 0 &&
745 !(address_left
== 0xffffffff && address_right
== 0xffff))
747 /* Check if this multicast address is wanted */
749 range
= (APTR
) unit
->rtl8169u_multicast_ranges
.mlh_Head
;
750 tail
= (APTR
) &unit
->rtl8169u_multicast_ranges
.mlh_Tail
;
753 while((range
!= tail
) && !accept
)
755 if((address_left
> range
->lower_bound_left
||
756 (address_left
== range
->lower_bound_left
&&
757 address_right
>= range
->lower_bound_right
)) &&
758 (address_left
< range
->upper_bound_left
||
759 (address_left
== range
->upper_bound_left
&&
760 address_right
<= range
->upper_bound_right
)))
762 RTLD(bug("[%s] AddressFilter: packet accepted.\n", unit
->rtl8169u_name
))
765 range
= (APTR
) range
->node
.mln_Succ
;
770 unit
->rtl8169u_special_stats
[S2SS_ETHERNET_BADMULTICAST
& 0xffff]++;
779 AROS_UFH3(void, RTL8169_Schedular
,
780 AROS_UFHA(STRPTR
, argPtr
, A0
),
781 AROS_UFHA(ULONG
, argSize
, D0
),
782 AROS_UFHA(struct ExecBase
*, SysBase
, A6
))
786 struct Task
*taskSelf
= FindTask(NULL
);
787 struct RTL8169Startup
*sm_UD
= taskSelf
->tc_UserData
;
788 struct RTL8169Unit
*unit
= sm_UD
->rtl8169sm_Unit
;
790 LIBBASETYPEPTR LIBBASE
= unit
->rtl8169u_device
;
791 struct MsgPort
*reply_port
, *input
;
793 RTLD(bug("[%s] RTL8169_Schedular()\n", taskSelf
->tc_Node
.ln_Name
))
794 RTLD(bug("[%s] RTL8169_Schedular: Setting up device '%s'\n", taskSelf
->tc_Node
.ln_Name
, unit
->rtl8169u_name
))
796 if ((reply_port
= CreateMsgPort()) == NULL
)
798 RTLD(bug("[%s] RTL8169_Schedular: Failed to create Reply message port\n", taskSelf
->tc_Node
.ln_Name
))
801 if ((input
= CreateMsgPort()) == NULL
)
803 RTLD(bug("[%s] RTL8169_Schedular: Failed to create Input message port\n", taskSelf
->tc_Node
.ln_Name
))
806 unit
->rtl8169u_input_port
= input
;
808 if ((unit
->rtl8169u_TimerSlowPort
= CreateMsgPort()) != NULL
)
810 unit
->rtl8169u_TimerSlowReq
= (struct timerequest
*) CreateIORequest(
811 (struct MsgPort
*) unit
->rtl8169u_TimerSlowPort
,
812 sizeof(struct timerequest
));
814 if (unit
->rtl8169u_TimerSlowReq
)
816 if (!OpenDevice("timer.device", UNIT_MICROHZ
,
817 (struct IORequest
*)unit
->rtl8169u_TimerSlowReq
, 0))
819 struct Message
*msg
= AllocVec(sizeof(struct Message
), MEMF_PUBLIC
| MEMF_CLEAR
);
822 RTLD(bug("[%s] RTL8169_Schedular: Got MICROHZ unit of timer.device\n", taskSelf
->tc_Node
.ln_Name
))
824 unit
->initialize(unit
);
826 msg
->mn_ReplyPort
= reply_port
;
827 msg
->mn_Length
= sizeof(struct Message
);
829 RTLD(bug("[%s] RTL8169_Schedular: Setup complete. Sending handshake\n", taskSelf
->tc_Node
.ln_Name
))
830 PutMsg(sm_UD
->rtl8169sm_SyncPort
, msg
);
831 WaitPort(reply_port
);
836 RTLD(bug("[%s] RTL8169_Schedular: entering forever loop ... \n", taskSelf
->tc_Node
.ln_Name
))
838 unit
->rtl8169u_signal_0
= AllocSignal(-1);
839 unit
->rtl8169u_signal_1
= AllocSignal(-1);
840 unit
->rtl8169u_signal_2
= AllocSignal(-1);
841 unit
->rtl8169u_signal_3
= AllocSignal(-1);
843 sigset
= 1 << input
->mp_SigBit
|
844 1 << unit
->rtl8169u_signal_0
|
845 1 << unit
->rtl8169u_signal_1
|
846 1 << unit
->rtl8169u_signal_2
|
847 1 << unit
->rtl8169u_signal_3
;
850 ULONG recvd
= Wait(sigset
);
851 if (recvd
& 1 << unit
->rtl8169u_signal_0
)
854 * Shutdown process. Driver should close everything
855 * already and waits for our process to complete. Free
856 * memory allocated here and kindly return.
858 unit
->deinitialize(unit
);
859 CloseDevice((struct IORequest
*) unit
->rtl8169u_TimerSlowReq
);
860 DeleteIORequest((struct IORequest
*) unit
->rtl8169u_TimerSlowReq
);
861 DeleteMsgPort(unit
->rtl8169u_TimerSlowPort
);
862 DeleteMsgPort(input
);
863 DeleteMsgPort(reply_port
);
865 RTLD(bug("[%s] RTL8169_Schedular: Process shutdown.\n", taskSelf
->tc_Node
.ln_Name
))
868 else if (recvd
& (1 << input
->mp_SigBit
))
870 struct IOSana2Req
*io
;
872 /* Handle incoming transactions */
873 while ((io
= (struct IOSana2Req
*) GetMsg(input
)) != NULL
)
875 RTLD(bug("[%s] RTL8169_Schedular: Handle incoming transaction.\n",
876 taskSelf
->tc_Node
.ln_Name
))
877 ObtainSemaphore(&unit
->rtl8169u_unit_lock
);
878 handle_request(LIBBASE
, io
);
883 RTLD(bug("[%s] RTL8169_Schedular: Handle incoming signal.\n", taskSelf
->tc_Node
.ln_Name
))
884 /* Handle incoming signals */
894 static struct AddressRange
*FindMulticastRange(LIBBASETYPEPTR LIBBASE
, struct RTL8169Unit
*unit
,
895 ULONG lower_bound_left
, UWORD lower_bound_right
, ULONG upper_bound_left
, UWORD upper_bound_right
)
897 struct AddressRange
*range
, *tail
;
900 range
= (APTR
) unit
->rtl8169u_multicast_ranges
.mlh_Head
;
901 tail
= (APTR
) &unit
->rtl8169u_multicast_ranges
.mlh_Tail
;
903 while((range
!= tail
) && !found
)
905 if((lower_bound_left
== range
->lower_bound_left
) &&
906 (lower_bound_right
== range
->lower_bound_right
) &&
907 (upper_bound_left
== range
->upper_bound_left
) &&
908 (upper_bound_right
== range
->upper_bound_right
))
914 range
= (APTR
) range
->node
.mln_Succ
;
926 BOOL
AddMulticastRange(LIBBASETYPEPTR LIBBASE
, struct RTL8169Unit
*unit
, const UBYTE
*lower_bound
,
927 const UBYTE
*upper_bound
)
929 struct AddressRange
*range
;
930 ULONG lower_bound_left
, upper_bound_left
;
931 UWORD lower_bound_right
, upper_bound_right
;
933 lower_bound_left
= AROS_BE2LONG(*((ULONG
*) lower_bound
));
934 lower_bound_right
= AROS_BE2WORD(*((UWORD
*) (lower_bound
+ 4)));
935 upper_bound_left
= AROS_BE2LONG(*((ULONG
*) upper_bound
));
936 upper_bound_right
= AROS_BE2WORD(*((UWORD
*) (upper_bound
+ 4)));
938 range
= FindMulticastRange(LIBBASE
,
951 range
= AllocMem(sizeof(struct AddressRange
), MEMF_PUBLIC
);
954 range
->lower_bound_left
= lower_bound_left
;
955 range
->lower_bound_right
= lower_bound_right
;
956 range
->upper_bound_left
= upper_bound_left
;
957 range
->upper_bound_right
= upper_bound_right
;
958 range
->add_count
= 1;
961 AddTail((APTR
)&unit
->rtl8169u_multicast_ranges
, (APTR
) range
);
964 if (unit
->rtl8169u_range_count
++ == 0)
966 unit
->rtl8169u_flags
|= IFF_ALLMULTI
;
967 unit
->set_multicast(unit
);
972 return range
!= NULL
;
975 BOOL
RemMulticastRange(LIBBASETYPEPTR LIBBASE
,
976 struct RTL8169Unit
*unit
,
977 const UBYTE
*lower_bound
,
978 const UBYTE
*upper_bound
)
980 struct AddressRange
*range
;
981 ULONG lower_bound_left
, upper_bound_left
;
982 UWORD lower_bound_right
, upper_bound_right
;
984 lower_bound_left
= AROS_BE2LONG(*((ULONG
*)lower_bound
));
985 lower_bound_right
= AROS_BE2WORD(*((UWORD
*)(lower_bound
+ 4)));
986 upper_bound_left
= AROS_BE2LONG(*((ULONG
*)upper_bound
));
987 upper_bound_right
= AROS_BE2WORD(*((UWORD
*)(upper_bound
+ 4)));
989 range
= FindMulticastRange(LIBBASE
, unit
, lower_bound_left
, lower_bound_right
,
990 upper_bound_left
, upper_bound_right
);
994 if(--range
->add_count
== 0)
999 FreeMem(range
, sizeof(struct AddressRange
));
1001 if (--unit
->rtl8169u_range_count
== 0)
1003 unit
->rtl8169u_flags
&= ~IFF_ALLMULTI
;
1004 unit
->set_multicast(unit
);
1008 return range
!= NULL
;
1012 * Create new RTL8169 ethernet device unit
1014 struct RTL8169Unit
*CreateUnit(struct RTL8169Base
*RTL8169DeviceBase
, OOP_Object
*pciDevice
, IPTR CardRevision
)
1016 struct RTL8169Unit
*unit
;
1017 BOOL success
= TRUE
;
1022 #if defined(RTL_DEBUG)
1023 BOOL doDebug
= TRUE
;
1025 /* TODO: Get option to debug from somewhere .. */
1026 BOOL doDebug
= FALSE
;
1029 if ((unit
= AllocMem(sizeof(struct RTL8169Unit
), MEMF_PUBLIC
| MEMF_CLEAR
)) != NULL
)
1031 IPTR mmiobase
, mmiolen
, type
;
1033 BOOL mmioerror
= FALSE
;
1035 RTLD(bug("[rtl8169] CreateUnit()\n"))
1038 unit
->rtl8169u_flags
|= IFF_DEBUG
;
1040 unit
->rtl8169u_UnitNum
= RTL8169DeviceBase
->rtl8169b_UnitCount
++;
1042 unit
->rtl8169u_Sana2Info
.HardwareType
= S2WireType_Ethernet
;
1043 unit
->rtl8169u_Sana2Info
.MTU
= ETH_MTU
;
1044 unit
->rtl8169u_Sana2Info
.AddrFieldSize
= 8 * ETH_ADDRESSSIZE
;
1046 // Determine which configuration to use for this card
1047 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_VendorID
, &VendorId
);
1048 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_ProductID
, &ProductId
);
1050 unit
->rtl8169u_config
= UNKNOWN_CFG
;
1052 for(i
= 0; i
< NBR_CARDS
; i
++)
1054 if(cards
[i
].vendorID
== VendorId
&&
1055 cards
[i
].productID
== ProductId
)
1057 unit
->rtl8169u_config
= cards
[i
].config
;
1062 switch(unit
->rtl8169u_config
)
1065 unit
->rtl8169u_intr_event
= SYSErr
| LinkChg
| RxOverflow
|
1066 RxFIFOOver
| TxErr
| TxOK
| RxOK
| RxErr
;
1067 unit
->rtl8169u_napi_event
= RxFIFOOver
| TxErr
| TxOK
| RxOK
| RxOverflow
;
1070 unit
->rtl8169u_intr_event
= SYSErr
| LinkChg
| RxOverflow
| PCSTimeout
|
1071 RxFIFOOver
| TxErr
| TxOK
| RxOK
| RxErr
;
1072 unit
->rtl8169u_napi_event
= TxErr
| TxOK
| RxOK
| RxOverflow
;
1077 unit
->rtl8169u_intr_event
= SYSErr
| LinkChg
| RxOverflow
|
1078 TxErr
| TxOK
| RxOK
| RxErr
;
1079 unit
->rtl8169u_napi_event
= RxFIFOOver
| TxErr
| TxOK
| RxOK
| RxOverflow
;
1083 if ((unit
->rtl8169u_name
= AllocVec(8 + (unit
->rtl8169u_UnitNum
/ 10) + 2,
1084 MEMF_CLEAR
| MEMF_PUBLIC
)) == NULL
)
1086 FreeMem(unit
, sizeof(struct RTL8169Unit
));
1089 sprintf((char *) unit
->rtl8169u_name
, "rtl8169.%d", unit
->rtl8169u_UnitNum
);
1091 RTLD(bug("[rtl8169] CreateUnit: Unit allocated @ 0x%p\n", unit
))
1093 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Driver
, (APTR
) &driver
);
1095 unit
->rtl8169u_device
= RTL8169DeviceBase
;
1096 unit
->rtl8169u_PCIDevice
= pciDevice
;
1097 unit
->rtl8169u_PCIDriver
= driver
;
1099 unit
->rtl8169u_mtu
= unit
->rtl8169u_Sana2Info
.MTU
;
1101 InitSemaphore(&unit
->rtl8169u_unit_lock
);
1102 NEWLIST(&unit
->rtl8169u_Openers
);
1103 NEWLIST(&unit
->rtl8169u_multicast_ranges
);
1104 NEWLIST(&unit
->rtl8169u_type_trackers
);
1106 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_INTLine
, &unit
->rtl8169u_IRQ
);
1107 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Base0
, (IPTR
*)&unit
->rtl8169u_BaseIO
);
1108 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Base1
, &mmiobase
);
1109 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Size1
, &mmiolen
);
1110 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Type1
, &type
);
1113 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Base2
, &mmiobase
);
1114 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Size2
, &mmiolen
);
1115 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Type2
, &type
);
1118 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Base3
, &mmiobase
);
1119 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Size3
, &mmiolen
);
1120 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Type3
, &type
);
1123 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Base4
, &mmiobase
);
1124 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Size4
, &mmiolen
);
1125 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Type4
, &type
);
1128 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Base5
, &mmiobase
);
1129 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Size5
, &mmiolen
);
1130 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Type5
, &type
);
1136 RTLD(bug("[%s] CreateUnit: INT:%d, base0:0x%p, base2:0x%p, size2:%d\n", unit
->rtl8169u_name
,
1137 unit
->rtl8169u_IRQ
, unit
->rtl8169u_BaseIO
, mmiobase
, mmiolen
))
1139 if (type
& ADDRF_IO
)
1141 RTLD(bug("[%s] CreateUnit: MMIO Region of wrong type!\n", unit
->rtl8169u_name
))
1145 if (mmiolen
< R8169_REGS_SIZE
)
1147 RTLD(bug("[%s] CreateUnit: Invalid MMIO Reg size (%d, expected %d)\n", unit
->rtl8169u_name
,
1148 mmiolen
, R8169_REGS_SIZE
))
1153 HIDD_PCIDevice_Obtain(pciDevice
,
1154 RTL8169DeviceBase
->rtl8169b_Device
.dd_Library
.lib_Node
.ln_Name
))
1156 RTLD(bug("[%s] CreateUnit: Device is already owned\n", unit
->rtl8169u_name
))
1162 FreeMem(unit
->rtl8169u_name
, 8 + (unit
->rtl8169u_UnitNum
/10) + 2);
1163 FreeMem(unit
, sizeof(struct RTL8169Unit
));
1167 unit
->rtl8169u_SizeMem
= R8169_REGS_SIZE
;
1168 unit
->rtl8169u_BaseMem
= HIDD_PCIDriver_MapPCI(driver
, (APTR
)mmiobase
, unit
->rtl8169u_SizeMem
);
1170 if (unit
->rtl8169u_BaseMem
!= NULL
)
1172 struct TagItem attrs
[] =
1174 { aHidd_PCIDevice_isIO
, TRUE
},
1175 { aHidd_PCIDevice_isMEM
, TRUE
},
1176 { aHidd_PCIDevice_isMaster
, TRUE
},
1179 OOP_SetAttrs(pciDevice
, (struct TagItem
*)&attrs
);
1181 RTLD(bug("[%s] CreateUnit: PCI_BaseMem @ 0x%p\n", unit
->rtl8169u_name
, unit
->rtl8169u_BaseMem
))
1183 unit
->rtl8169u_DelayPort
.mp_SigBit
= SIGB_SINGLE
;
1184 unit
->rtl8169u_DelayPort
.mp_Flags
= PA_SIGNAL
;
1185 unit
->rtl8169u_DelayPort
.mp_SigTask
= FindTask(NULL
);
1186 unit
->rtl8169u_DelayPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
1187 NEWLIST(&unit
->rtl8169u_DelayPort
.mp_MsgList
);
1189 unit
->rtl8169u_DelayReq
.tr_node
.io_Message
.mn_ReplyPort
= &unit
->rtl8169u_DelayPort
;
1190 unit
->rtl8169u_DelayReq
.tr_node
.io_Message
.mn_Length
= sizeof(struct timerequest
);
1192 OpenDevice((STRPTR
) "timer.device", UNIT_MICROHZ
, (struct IORequest
*) &unit
->rtl8169u_DelayReq
, 0);
1194 if ((unit
->rtl8169u_priv
= AllocMem(sizeof(struct rtl8169_priv
), MEMF_PUBLIC
| MEMF_CLEAR
)) != NULL
)
1196 struct Message
*msg
;
1198 unit
->rtl8169u_priv
->pci_dev
= unit
;
1199 InitSemaphore(&unit
->rtl8169u_priv
->lock
);
1201 unit
->rtl8169u_irqhandler
.is_Node
.ln_Type
= NT_INTERRUPT
;
1202 unit
->rtl8169u_irqhandler
.is_Node
.ln_Pri
= 100;
1203 unit
->rtl8169u_irqhandler
.is_Node
.ln_Name
= LIBBASE
->rtl8169b_Device
.dd_Library
.lib_Node
.ln_Name
;
1204 unit
->rtl8169u_irqhandler
.is_Code
= (VOID_FUNC
)RTL8169_IntHandlerF
;
1205 unit
->rtl8169u_irqhandler
.is_Data
= unit
;
1207 unit
->rtl8169u_touthandler
.is_Node
.ln_Type
= NT_INTERRUPT
;
1208 unit
->rtl8169u_touthandler
.is_Node
.ln_Pri
= 100;
1209 unit
->rtl8169u_touthandler
.is_Node
.ln_Name
= LIBBASE
->rtl8169b_Device
.dd_Library
.lib_Node
.ln_Name
;
1210 unit
->rtl8169u_touthandler
.is_Code
= (VOID_FUNC
)RTL8169_TimeoutHandlerF
;
1211 unit
->rtl8169u_touthandler
.is_Data
= unit
;
1213 unit
->rtl8169u_tx_int
.is_Node
.ln_Name
= unit
->rtl8169u_name
;
1214 unit
->rtl8169u_tx_int
.is_Code
= (VOID_FUNC
)RTL8169_TX_IntF
;
1215 unit
->rtl8169u_tx_int
.is_Data
= unit
;
1217 for (i
= 0; i
< REQUEST_QUEUE_COUNT
; i
++)
1219 struct MsgPort
*port
= AllocMem(sizeof(struct MsgPort
), MEMF_PUBLIC
| MEMF_CLEAR
);
1221 unit
->rtl8169u_request_ports
[i
] = port
;
1223 if (port
== NULL
) success
= FALSE
;
1227 NEWLIST(&port
->mp_MsgList
);
1228 port
->mp_Flags
= PA_IGNORE
;
1229 port
->mp_SigTask
= &unit
->rtl8169u_tx_int
;
1233 // (All others are PA_IGNORE)
1234 unit
->rtl8169u_request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
1238 struct RTL8169Startup
*sm_UD
;
1241 if ((sm_UD
= AllocMem(sizeof(struct RTL8169Startup
), MEMF_PUBLIC
| MEMF_CLEAR
)) != NULL
)
1243 sprintf((char *) tmpbuff
, RTL8169_TASK_NAME
, unit
->rtl8169u_name
);
1245 sm_UD
->rtl8169sm_SyncPort
= CreateMsgPort();
1246 sm_UD
->rtl8169sm_Unit
= unit
;
1248 rtl8169_get_functions(unit
);
1250 unit
->rtl8169u_Process
= CreateNewProcTags(
1251 NP_Entry
, (IPTR
)RTL8169_Schedular
,
1253 NP_Synchronous
, FALSE
,
1255 NP_UserData
, (IPTR
)sm_UD
,
1256 NP_StackSize
, 140960,
1259 WaitPort(sm_UD
->rtl8169sm_SyncPort
);
1260 msg
= GetMsg(sm_UD
->rtl8169sm_SyncPort
);
1262 DeleteMsgPort(sm_UD
->rtl8169sm_SyncPort
);
1263 FreeMem(sm_UD
, sizeof(struct RTL8169Startup
));
1265 RTLD(bug("[%s] CreateUnit: Device Initialised. Unit %d @ %p\n",
1266 unit
->rtl8169u_name
,
1267 unit
->rtl8169u_UnitNum
,
1273 RTLD(bug("[%s] ERRORS occured during Device setup - ABORTING\n", unit
->rtl8169u_name
))
1277 RTLD(bug("[rtl8169] PANIC! Couldn't get MMIO area. Aborting\n"))
1279 DeleteUnit(RTL8169DeviceBase
, unit
);
1283 bug("[rtl8169] CreateUnit: Failed to Allocate Unit storage!\n");
1289 * DeleteUnit - removes selected unit. Frees all resources and structures.
1291 * The caller should be sure, that given unit is really ready to be freed.
1293 void DeleteUnit(struct RTL8169Base
*RTL8169DeviceBase
, struct RTL8169Unit
*Unit
)
1300 if (Unit
->rtl8169u_Process
)
1302 /* Tell our process to quit, and wait until it does so */
1303 Signal(&Unit
->rtl8169u_Process
->pr_Task
,
1304 1 << Unit
->rtl8169u_signal_0
);
1305 sprintf((char *) tmpbuff
, RTL8169_TASK_NAME
, Unit
->rtl8169u_name
);
1306 while (FindTask(tmpbuff
) != NULL
)
1310 for (i
=0; i
< REQUEST_QUEUE_COUNT
; i
++)
1312 if (Unit
->rtl8169u_request_ports
[i
] != NULL
)
1313 FreeMem(Unit
->rtl8169u_request_ports
[i
], sizeof(struct MsgPort
));
1315 Unit
->rtl8169u_request_ports
[i
] = NULL
;
1318 if (Unit
->rtl8169u_priv
)
1320 FreeMem(Unit
->rtl8169u_priv
, sizeof(struct rtl8169_priv
));
1321 Unit
->rtl8169u_priv
= NULL
;
1324 if (Unit
->rtl8169u_BaseMem
)
1326 HIDD_PCIDriver_UnmapPCI(Unit
->rtl8169u_PCIDriver
,
1327 (APTR
)Unit
->rtl8169u_BaseMem
,
1328 Unit
->rtl8169u_SizeMem
);
1331 HIDD_PCIDevice_Release(Unit
->rtl8169u_PCIDevice
);
1332 FreeMem(Unit
, sizeof(struct RTL8169Unit
));