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
53 extern UBYTE
MMIO_R8(UBYTE
*);
54 extern UWORD
MMIO_R16(UWORD
*);
55 extern ULONG
MMIO_R32(ULONG
*);
56 extern void MMIO_W8(UBYTE
*, UBYTE
);
57 extern void MMIO_W16(UWORD
*, UWORD
);
58 extern void MMIO_W32(ULONG
*, ULONG
);
60 extern void rtl8168_CheckLinkStatus(struct net_device
*);
63 * Report incoming events to all hyphotetical event receivers
65 VOID
ReportEvents(struct RTL8168Base
*RTL8168DeviceBase
, struct RTL8168Unit
*unit
, ULONG events
)
67 struct IOSana2Req
*request
, *tail
, *next_request
;
70 list
= &unit
->rtl8168u_request_ports
[EVENT_QUEUE
]->mp_MsgList
;
71 next_request
= (APTR
)list
->lh_Head
;
72 tail
= (APTR
)&list
->lh_Tail
;
74 /* Go through list of event listeners. If send messages to receivers if event found */
76 while(next_request
!= tail
)
78 request
= next_request
;
79 next_request
= (APTR
)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
81 if((request
->ios2_WireError
&events
) != 0)
83 request
->ios2_WireError
= events
;
84 Remove((APTR
)request
);
85 ReplyMsg((APTR
)request
);
93 struct TypeStats
*FindTypeStats(struct RTL8168Base
*RTL8168DeviceBase
, struct RTL8168Unit
*unit
,
94 struct MinList
*list
, ULONG packet_type
)
96 struct TypeStats
*stats
, *tail
;
99 stats
= (APTR
)list
->mlh_Head
;
100 tail
= (APTR
)&list
->mlh_Tail
;
102 while(stats
!= tail
&& !found
)
104 if(stats
->packet_type
== packet_type
)
107 stats
= (APTR
)stats
->node
.mln_Succ
;
116 void FlushUnit(LIBBASETYPEPTR LIBBASE
, struct RTL8168Unit
*unit
, UBYTE last_queue
, BYTE error
)
118 struct IORequest
*request
;
120 struct Opener
*opener
, *tail
;
122 RTLD(bug("[%s] unit.FlushUnit\n", unit
->rtl8168u_name
))
124 /* Abort queued operations */
125 for (i
=0; i
<= last_queue
; i
++)
127 while ((request
= (APTR
)GetMsg(unit
->rtl8168u_request_ports
[i
])) != NULL
)
129 request
->io_Error
= IOERR_ABORTED
;
130 ReplyMsg((struct Message
*)request
);
134 opener
= (APTR
)unit
->rtl8168u_Openers
.mlh_Head
;
135 tail
= (APTR
)unit
->rtl8168u_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 void rtl8168_MarkToASIC(struct RxDesc
*desc
, ULONG rx_buf_sz
)
151 ULONG eor
= AROS_LE2LONG(desc
->opts1
) & RingEnd
;
153 desc
->opts1
= AROS_LONG2LE(DescOwn
| eor
| rx_buf_sz
);
156 /* Interrupt Rx Support Function ..
157 * It's duty is to iterate throgh RX queue searching for new packets.
159 void RTL8168_Rx_Process(struct RTL8168Unit
*unit
)
161 struct RTL8168Base
*RTL8168DeviceBase
= unit
->rtl8168u_device
;
162 struct rtl8168_priv
*np
= unit
->rtl8168u_priv
;
163 // APTR base = unit->rtl8168u_BaseMem;
165 struct TypeStats
*tracker
;
167 struct Opener
*opener
, *opener_tail
;
168 struct IOSana2Req
*request
, *request_tail
;
169 BOOL accepted
, is_orphan
;
171 RTLD(bug("[%s] RTL8168_Rx_Process() !!!!\n", unit
->rtl8168u_name
))
173 struct eth_frame
*frame
;
175 unsigned short cur_rx
, rx_left
;
177 rx_left
= NUM_RX_DESC
- np
->dirty_rx
;
179 RTLD(bug("[%s] RTL8168_Rx_Process: cur_rx = %d, rx_left = %d, dirty = %d\n", unit
->rtl8168u_name
, cur_rx
, rx_left
, np
->dirty_rx
))
181 for (; rx_left
> 0; rx_left
--, cur_rx
++) {
182 unsigned int entry
= cur_rx
% NUM_RX_DESC
;
183 struct RxDesc
*desc
= np
->RxDescArray
+ entry
;
186 status
= AROS_LE2LONG(desc
->opts1
);
188 if (status
& DescOwn
)
191 RTLD(bug("[%s] RTL8168_Rx_Process: Packet %d\n", unit
->rtl8168u_name
, entry
))
193 if (status
& RxRES
) {
194 RTLD(bug("[%s] RTL8168_Rx_Process: Rx ERROR, status = %08x\n",
195 unit
->rtl8168u_name
, status
))
197 /* TODO: record rx errors .. */
198 /* RTLDEV->stats.rx_errors++;
200 if (status & (RxRWT | RxRUNT))
201 RTLDEV->stats.rx_length_errors++;
203 RTLDEV->stats.rx_crc_errors++;
205 rtl8168_MarkToASIC(desc
, np
->rx_buf_sz
);
209 int pkt_size
= (status
& 0x00003FFF) - ETH_CRCSIZE
;
211 frame
= (APTR
)(IPTR
)desc
->addr
;
212 RTLD(bug("[%s] RTL8168_Rx_Process: frame @ %p, pkt_size=%d\n", unit
->rtl8168u_name
, frame
, pkt_size
))
214 /* got a valid packet - forward it to the network core */
219 for (j
= 0; j
< pkt_size
; j
++) {
226 bug("[%s] RTL8168_Rx_Process: %03x:", unit
->rtl8168u_name
, j
);
228 bug(" %02x", ((unsigned char*)frame
)[j
]);
233 /* Check for address validity */
234 if(AddressFilter(LIBBASE
, unit
, frame
->eth_packet_dest
))
236 /* Packet is addressed to this driver */
237 packet_type
= AROS_BE2WORD(frame
->eth_packet_type
);
238 RTLD(bug("[%s] RTL8168_Rx_Process: Packet IP accepted with type = %d\n", unit
->rtl8168u_name
, packet_type
))
240 opener
= (APTR
)unit
->rtl8168u_Openers
.mlh_Head
;
241 opener_tail
= (APTR
)&unit
->rtl8168u_Openers
.mlh_Tail
;
243 /* Offer packet to every opener */
244 while(opener
!= opener_tail
)
246 request
= (APTR
)opener
->read_port
.mp_MsgList
.lh_Head
;
247 request_tail
= (APTR
)&opener
->read_port
.mp_MsgList
.lh_Tail
;
250 /* Offer packet to each request until it's accepted */
251 while((request
!= request_tail
) && !accepted
)
253 if((request
->ios2_PacketType
== packet_type
)
254 || ((request
->ios2_PacketType
<= ETH_MTU
)
255 && (packet_type
<= ETH_MTU
)))
257 RTLD(bug("[%s] RTL8168_Rx_Process: copy packet for opener ..\n", unit
->rtl8168u_name
))
258 CopyPacket(LIBBASE
, unit
, request
, pkt_size
, packet_type
, frame
);
261 request
= (struct IOSana2Req
*)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
267 opener
= (APTR
)opener
->node
.mln_Succ
;
270 /* If packet was unwanted, give it to S2_READORPHAN request */
273 unit
->rtl8168u_stats
.UnknownTypesReceived
++;
275 if(!IsMsgPortEmpty(unit
->rtl8168u_request_ports
[ADOPT_QUEUE
]))
277 CopyPacket(LIBBASE
, unit
,
278 (APTR
)unit
->rtl8168u_request_ports
[ADOPT_QUEUE
]->
279 mp_MsgList
.lh_Head
, pkt_size
, packet_type
, frame
);
280 RTLD(bug("[%s] RTL8168_Rx_Process: packet copied to orphan queue\n", unit
->rtl8168u_name
))
284 rtl8168_MarkToASIC(desc
, (ULONG
)np
->rx_buf_sz
);
286 /* Update remaining statistics */
287 tracker
= FindTypeStats(LIBBASE
, unit
, &unit
->rtl8168u_type_trackers
, packet_type
);
291 tracker
->stats
.PacketsReceived
++;
292 tracker
->stats
.BytesReceived
+= pkt_size
;
295 unit
->rtl8168u_stats
.PacketsReceived
++;
299 RTLD(bug("[%s] RTL8168_Rx_Process: Rx Packet Processing complete\n", unit
->rtl8168u_name
))
303 * Interrupt generated by Cause() to push new packets into the NIC interface
305 static AROS_INTH1(RTL8168_TX_IntF
, struct RTL8168Unit
*, unit
)
309 struct rtl8168_priv
*np
= unit
->rtl8168u_priv
;
310 struct RTL8168Base
*RTL8168DeviceBase
= unit
->rtl8168u_device
;
311 APTR base
= unit
->rtl8168u_BaseMem
;
314 BOOL proceed
= FALSE
; /* Fails by default */
316 RTLD(bug("[%s] RTL8168_TX_IntF()\n", unit
->rtl8168u_name
))
318 /* send packet only if there is free space on tx queue. Otherwise do nothing */
319 if (!netif_queue_stopped(unit
))
321 UWORD packet_size
, data_size
;
322 struct IOSana2Req
*request
;
323 struct Opener
*opener
;
327 struct MsgPort
*port
;
329 proceed
= TRUE
; /* Success by default */
330 port
= unit
->rtl8168u_request_ports
[WRITE_QUEUE
];
332 /* Still no error and there are packets to be sent? */
333 while(proceed
&& (!IsMsgPortEmpty(port
)))
335 nr
= np
->cur_tx
% NUM_TX_DESC
;
338 request
= (APTR
)port
->mp_MsgList
.lh_Head
;
339 data_size
= packet_size
= request
->ios2_DataLength
;
341 opener
= (APTR
)request
->ios2_BufferManagement
;
343 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
345 packet_size
+= ETH_PACKET_DATA
;
348 if ((!(AROS_LE2LONG(np
->TxDescArray
[nr
].opts1
) & DescOwn
)) &&
349 ((np
->TxDescArray
[nr
].addr
= (IPTR
)AllocMem(packet_size
, MEMF_CLEAR
| MEMF_PUBLIC
)) != 0))
351 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
353 CopyMem(request
->ios2_DstAddr
, &((struct eth_frame
*)(IPTR
)np
->TxDescArray
[nr
].addr
)->eth_packet_dest
, ETH_ADDRESSSIZE
);
354 CopyMem(unit
->rtl8168u_dev_addr
, &((struct eth_frame
*)(IPTR
)np
->TxDescArray
[nr
].addr
)->eth_packet_source
, ETH_ADDRESSSIZE
);
355 ((struct eth_frame
*)(IPTR
)np
->TxDescArray
[nr
].addr
)->eth_packet_type
= AROS_WORD2BE(request
->ios2_PacketType
);
357 buffer
= (APTR
)&((struct eth_frame
*)(IPTR
)np
->TxDescArray
[nr
].addr
)->eth_packet_data
;
360 buffer
= (APTR
)(IPTR
)np
->TxDescArray
[nr
].addr
;
362 if (!opener
->tx_function(buffer
, request
->ios2_Data
, data_size
))
364 error
= S2ERR_NO_RESOURCES
;
365 wire_error
= S2WERR_BUFF_ERROR
;
366 ReportEvents(LIBBASE
, unit
,
367 S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
371 // Now the packet is already in TX buffer, update flags for NIC
375 APTR packet
= (APTR
)(IPTR
)np
->TxDescArray
[nr
].addr
;
376 bug("[%s] RTL8168_TX_IntF: packet %d @ %p [type = %d] queued for transmission.\n", unit
->rtl8168u_name
, nr
, (APTR
)(IPTR
)np
->TxDescArray
[nr
].addr
, AROS_BE2WORD(((struct eth_frame
*)packet
)->eth_packet_type
))
381 for (j
= 0; j
< packet_size
; j
++) {
388 bug("[%s] RTL8168_TX_IntF: %03x:", unit
->rtl8168u_name
, j
);
390 bug(" %02x", ((unsigned char*)np
->TxDescArray
[nr
].addr
)[j
]);
395 // Set the ring details for the packet ..
396 np
->TxDescArray
[nr
].opts1
= AROS_LONG2LE(DescOwn
| FirstFrag
| LastFrag
| packet_size
| (RingEnd
* !((nr
+ 1) % NUM_TX_DESC
)));
397 np
->TxDescArray
[nr
].opts2
= AROS_LONG2LE(0);
399 /* TODO: Perhaps set the Tx Poll bit after we leave the while loop .. */
400 RTL_W8(base
+ (TxPoll
), NPQ
); /* set polling bit */
404 request
->ios2_Req
.io_Error
= error
;
405 request
->ios2_WireError
= wire_error
;
407 Remove((APTR
)request
);
409 ReplyMsg((APTR
)request
);
416 // If we've just run out of free space on the TX queue, stop
417 // it and give up pushing further frames
418 if ( (try_count
+ 1) >= NUM_TX_DESC
)
420 RTLD(bug("[%s] output queue full!. Stopping [count = %d, NUM_TX_DESC = %d\n", unit
->rtl8168u_name
, try_count
, NUM_TX_DESC
))
421 netif_stop_queue(unit
);
427 /* Was there success? Enable incomming of new packets */
429 unit
->rtl8168u_request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
431 unit
->rtl8168u_request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_IGNORE
;
439 * Handle timeouts and other strange cases
441 static AROS_INTH1(RTL8168_TimeoutHandlerF
, struct RTL8168Unit
*, unit
)
446 struct Device
*TimerBase
= unit
->rtl8168u_TimerSlowReq
->tr_node
.io_Device
;
449 //RTLD(bug("[%s] RTL8168_TimeoutHandlerF()\n", unit->rtl8168u_name))
452 * If timeout timer is expected, and time elapsed - regenerate the
455 if (unit
->rtl8168u_toutNEED
&& (CmpTime(&time
, &unit
->rtl8168u_toutPOLL
) < 0))
457 unit
->rtl8168u_toutNEED
= FALSE
;
458 //Cause(&unit->rtl8168u_tx_end_int);
466 static void RTL8168_Tx_Cleanup(struct net_device
*unit
)
468 struct rtl8168_priv
*np
= unit
->rtl8168u_priv
;
469 unsigned int dirty_tx
, tx_left
;
470 struct TypeStats
*tracker
;
472 dirty_tx
= np
->dirty_tx
;
473 tx_left
= np
->cur_tx
- dirty_tx
;
475 while (tx_left
> 0) {
476 unsigned int entry
= dirty_tx
% NUM_TX_DESC
;
477 ULONG packet_size
, status
;
479 status
= AROS_LE2LONG(np
->TxDescArray
[entry
].opts1
);
481 if (status
& DescOwn
)
484 packet_size
= status
& 0x3FFF;
485 tracker
= FindTypeStats(unit
->rtl8168u_device
, unit
, &unit
->rtl8168u_type_trackers
, ((struct eth_frame
*)(IPTR
)np
->TxDescArray
[entry
].addr
)->eth_packet_type
);
488 tracker
->stats
.PacketsSent
++;
489 tracker
->stats
.BytesSent
+= packet_size
;
492 if (status
& LastFrag
) {
493 RTLD(bug("[%s] RTL8168_Tx_Cleanup: Released buffer %d (%d bytes)\n", unit
->rtl8168u_name
, entry
, packet_size
))
494 np
->TxDescArray
[entry
].opts1
= AROS_LONG2LE(RingEnd
);
495 np
->TxDescArray
[entry
].addr
= 0;
500 if (np
->dirty_tx
!= dirty_tx
) {
501 np
->dirty_tx
= dirty_tx
;
503 if (netif_queue_stopped(dev) &&
504 (TX_BUFFS_AVAIL(np) >= MAX_SKB_FRAGS)) {
505 netif_wake_queue(dev);
512 * Interrupt handler called whenever RTL8168 NIC interface generates interrupt.
514 static AROS_INTH1(RTL8168_IntHandlerF
, struct RTL8168Unit
*, unit
)
518 struct rtl8168_priv
*np
= unit
->rtl8168u_priv
;
519 APTR base
= unit
->rtl8168u_BaseMem
;
522 int boguscnt
= unit
->rtl8168u_device
->rtl8168b_MaxIntWork
;
524 UWORD intr_clean_mask
= SYSErr
| PCSTimeout
| SWInt
|
525 LinkChg
| RxDescUnavail
|
526 TxErr
| TxOK
| RxErr
| RxOK
;
528 RTL_W16(base
+ (IntrMask
), 0x0000);
530 RTLD(bug("[%s] RTL8168_IntHandlerF()!!!!!!!\n", unit
->rtl8168u_name
))
533 status
= RTL_R16(base
+ (IntrStatus
));
535 /* hotplug/major error/no more work/shared irq */
536 if ((status
== 0xFFFF) || !status
)
539 // if (!netif_running(unit)) {
540 // rtl8168_asic_down(unit);
544 status
&= (np
->intr_mask
| TxDescUnavail
);
545 RTL_W16(base
+ (IntrStatus
), intr_clean_mask
);
547 if (!(status
& unit
->rtl8168u_intr_mask
))
550 //Work around for rx fifo overflow
551 if (status
& RxFIFOOver
)
553 RTLD(bug("[%s] RTL8168_IntHandlerF: Rx FIFO overflow occured!\n", unit
->rtl8168u_name
))
554 if (np
->mcfg
== CFG_METHOD_1
) {
555 /*np->rx_fifo_overflow = 1;
556 netif_stop_queue(unit);
558 rtl8168_rx_clear(np);
559 rtl8168_init_ring(unit);
560 rtl8168_hw_start(unit);*/
561 RTL_W16(base
+ (IntrStatus
), RxFIFOOver
);
562 /*netif_wake_queue(unit);
563 np->rx_fifo_overflow = 0;*/
567 if (status
& SYSErr
) {
568 RTLD(bug("[%s] RTL8168_IntHandlerF: PCI error occured!\n", unit
->rtl8168u_name
))
569 // rtl8168_pcierr_interrupt(unit);
573 if (status
& LinkChg
)
575 RTLD(bug("[%s] RTL8168_IntHandlerF: Link Change!\n", unit
->rtl8168u_name
))
576 rtl8168_CheckLinkStatus(unit
);
579 if ((status
& TxOK
) && (status
& TxDescUnavail
))
581 RTL_W8(base
+ (TxPoll
), NPQ
); /* set polling bit */
582 RTL_W16(base
+ (IntrStatus
), TxDescUnavail
);
585 if (status
& (RxOK
| RxDescUnavail
| RxFIFOOver
))
587 RTLD(bug("[%s] RTL8168_IntHandlerF: Packet Reception detected!\n", unit
->rtl8168u_name
))
588 RTL8168_Rx_Process(unit
);
589 // rtl8168_rx_interrupt(unit, np, np->mmio_addr, ~(u32)0);
592 if (status
& (TxOK
| TxErr
))
594 RTLD(bug("[%s] RTL8168_IntHandlerF: Packet Transmission detected!\n", unit
->rtl8168u_name
))
595 RTL8168_Tx_Cleanup(unit
);
598 } while (boguscnt
> 0);
601 RTLD(bug("[%s] RTL8168_IntHandlerF: Too much work at interrupt!\n", unit
->rtl8168u_name
))
602 /* Clear all interrupt sources. */
603 RTL_W16(base
+ (IntrStatus
), 0xffff);
606 RTL_W16(base
+ (IntrMask
), np
->intr_mask
);
613 VOID
CopyPacket(struct RTL8168Base
*RTL8168DeviceBase
, struct RTL8168Unit
*unit
,
614 struct IOSana2Req
*request
, UWORD packet_size
, UWORD packet_type
,
615 struct eth_frame
*buffer
)
617 struct Opener
*opener
;
618 BOOL filtered
= FALSE
;
620 const UBYTE broadcast
[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
622 RTLD(bug("[%s] CopyPacket(packet @ %x, len = %d)\n", unit
->rtl8168u_name
, buffer
, packet_size
))
624 /* Set multicast and broadcast flags */
626 request
->ios2_Req
.io_Flags
&= ~(SANA2IOF_BCAST
| SANA2IOF_MCAST
);
627 if (memcmp(buffer
->eth_packet_dest
, broadcast
, 6) == 0)
629 request
->ios2_Req
.io_Flags
|= SANA2IOF_BCAST
;
630 RTLD(bug("[%s] CopyPacket: BROADCAST Flag set\n", unit
->rtl8168u_name
))
632 else if((buffer
->eth_packet_dest
[0] & 0x1) != 0)
634 request
->ios2_Req
.io_Flags
|= SANA2IOF_MCAST
;
635 RTLD(bug("[%s] CopyPacket: MULTICAST Flag set\n", unit
->rtl8168u_name
))
638 /* Set source and destination addresses and packet type */
639 CopyMem(buffer
->eth_packet_source
, request
->ios2_SrcAddr
, ETH_ADDRESSSIZE
);
640 CopyMem(buffer
->eth_packet_dest
, request
->ios2_DstAddr
, ETH_ADDRESSSIZE
);
641 request
->ios2_PacketType
= packet_type
;
643 /* Adjust for cooked packet request */
645 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
647 packet_size
-= ETH_PACKET_DATA
;
648 ptr
= (UBYTE
*)&buffer
->eth_packet_data
[0];
652 ptr
= (UBYTE
*)buffer
;
655 request
->ios2_DataLength
= packet_size
;
657 RTLD(bug("[%s] CopyPacket: packet @ %x (%d bytes)\n", unit
->rtl8168u_name
, ptr
, packet_size
))
661 opener
= request
->ios2_BufferManagement
;
662 if((request
->ios2_Req
.io_Command
== CMD_READ
) &&
663 (opener
->filter_hook
!= NULL
))
664 if(!CallHookPkt(opener
->filter_hook
, request
, ptr
))
666 RTLD(bug("[%s] CopyPacket: packet filtered\n", unit
->rtl8168u_name
))
672 /* Copy packet into opener's buffer and reply packet */
673 RTLD(bug("[%s] CopyPacket: opener recieve packet .. ", unit
->rtl8168u_name
))
674 if(!opener
->rx_function(request
->ios2_Data
, ptr
, packet_size
))
676 RTLD(bug("ERROR occured!!\n"))
677 request
->ios2_Req
.io_Error
= S2ERR_NO_RESOURCES
;
678 request
->ios2_WireError
= S2WERR_BUFF_ERROR
;
679 ReportEvents(LIBBASE
, unit
, S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
| S2EVENT_RX
);
683 RTLD(bug("SUCCESS!!\n"))
686 Remove((APTR
)request
);
688 ReplyMsg((APTR
)request
);
689 RTLD(bug("[%s] CopyPacket: opener notified.\n", unit
->rtl8168u_name
))
693 BOOL
AddressFilter(struct RTL8168Base
*RTL8168DeviceBase
, struct RTL8168Unit
*unit
, UBYTE
*address
)
695 struct AddressRange
*range
, *tail
;
700 /* Check whether address is unicast/broadcast or multicast */
702 address_left
= AROS_BE2LONG(*((ULONG
*)address
));
703 address_right
= AROS_BE2WORD(*((UWORD
*)(address
+ 4)));
705 if((address_left
& 0x01000000) != 0 &&
706 !(address_left
== 0xffffffff && address_right
== 0xffff))
708 /* Check if this multicast address is wanted */
710 range
= (APTR
)unit
->rtl8168u_multicast_ranges
.mlh_Head
;
711 tail
= (APTR
)&unit
->rtl8168u_multicast_ranges
.mlh_Tail
;
714 while((range
!= tail
) && !accept
)
716 if((address_left
> range
->lower_bound_left
||
717 (address_left
== range
->lower_bound_left
&&
718 address_right
>= range
->lower_bound_right
)) &&
719 (address_left
< range
->upper_bound_left
||
720 (address_left
== range
->upper_bound_left
&&
721 address_right
<= range
->upper_bound_right
)))
723 range
= (APTR
)range
->node
.mln_Succ
;
727 unit
->rtl8168u_special_stats
[S2SS_ETHERNET_BADMULTICAST
& 0xffff]++;
735 AROS_UFH3(void, RTL8168_Schedular
,
736 AROS_UFHA(STRPTR
, argPtr
, A0
),
737 AROS_UFHA(ULONG
, argSize
, D0
),
738 AROS_UFHA(struct ExecBase
*, SysBase
, A6
))
742 struct Task
*taskSelf
= FindTask(NULL
);
743 struct RTL8168Startup
*sm_UD
= taskSelf
->tc_UserData
;
744 struct RTL8168Unit
*unit
= sm_UD
->rtl8168sm_Unit
;
746 LIBBASETYPEPTR LIBBASE
= unit
->rtl8168u_device
;
747 struct MsgPort
*reply_port
, *input
;
749 RTLD(bug("[%s] RTL8168_Schedular()\n", taskSelf
->tc_Node
.ln_Name
))
750 RTLD(bug("[%s] RTL8168_Schedular: Setting up device '%s'\n", taskSelf
->tc_Node
.ln_Name
, unit
->rtl8168u_name
))
752 if ((reply_port
= CreateMsgPort()) == NULL
)
754 RTLD(bug("[%s] RTL8168_Schedular: Failed to create Reply message port\n", taskSelf
->tc_Node
.ln_Name
))
757 if ((input
= CreateMsgPort()) == NULL
)
759 RTLD(bug("[%s] RTL8168_Schedular: Failed to create Input message port\n", taskSelf
->tc_Node
.ln_Name
))
762 unit
->rtl8168u_input_port
= input
;
764 if ((unit
->rtl8168u_TimerSlowPort
= CreateMsgPort()) != NULL
)
766 unit
->rtl8168u_TimerSlowReq
= (struct timerequest
*)
767 CreateIORequest((struct MsgPort
*)unit
->rtl8168u_TimerSlowPort
, sizeof(struct timerequest
));
769 if (unit
->rtl8168u_TimerSlowReq
)
771 if (!OpenDevice("timer.device", UNIT_MICROHZ
,
772 (struct IORequest
*)unit
->rtl8168u_TimerSlowReq
, 0))
774 struct Message
*msg
= AllocVec(sizeof(struct Message
), MEMF_PUBLIC
|MEMF_CLEAR
);
777 RTLD(bug("[%s] RTL8168_Schedular: Got MICROHZ unit of timer.device\n", taskSelf
->tc_Node
.ln_Name
))
779 unit
->initialize(unit
);
781 msg
->mn_ReplyPort
= reply_port
;
782 msg
->mn_Length
= sizeof(struct Message
);
784 RTLD(bug("[%s] RTL8168_Schedular: Setup complete. Sending handshake\n", taskSelf
->tc_Node
.ln_Name
))
785 PutMsg(sm_UD
->rtl8168sm_SyncPort
, msg
);
786 WaitPort(reply_port
);
791 RTLD(bug("[%s] RTL8168_Schedular: entering forever loop ... \n", taskSelf
->tc_Node
.ln_Name
))
793 unit
->rtl8168u_signal_0
= AllocSignal(-1);
794 unit
->rtl8168u_signal_1
= AllocSignal(-1);
795 unit
->rtl8168u_signal_2
= AllocSignal(-1);
796 unit
->rtl8168u_signal_3
= AllocSignal(-1);
798 sigset
= 1 << input
->mp_SigBit
|
799 1 << unit
->rtl8168u_signal_0
|
800 1 << unit
->rtl8168u_signal_1
|
801 1 << unit
->rtl8168u_signal_2
|
802 1 << unit
->rtl8168u_signal_3
;
805 ULONG recvd
= Wait(sigset
);
806 if (recvd
& unit
->rtl8168u_signal_0
)
809 * Shutdown process. Driver should close everything
810 * already and waits for our process to complete. Free
811 * memory allocared here and kindly return.
813 unit
->deinitialize(unit
);
814 CloseDevice((struct IORequest
*)unit
->rtl8168u_TimerSlowReq
);
815 DeleteIORequest((struct IORequest
*)unit
->rtl8168u_TimerSlowReq
);
816 DeleteMsgPort(unit
->rtl8168u_TimerSlowPort
);
817 DeleteMsgPort(input
);
818 DeleteMsgPort(reply_port
);
820 RTLD(bug("[%s] RTL8168_Schedular: Process shutdown.\n", taskSelf
->tc_Node
.ln_Name
))
823 else if (recvd
& (1 << input
->mp_SigBit
))
825 struct IOSana2Req
*io
;
827 /* Handle incoming transactions */
828 while ((io
= (struct IOSana2Req
*)GetMsg(input
)) != NULL
)
830 RTLD(bug("[%s] RTL8168_Schedular: Handle incomming transaction.\n", taskSelf
->tc_Node
.ln_Name
))
831 ObtainSemaphore(&unit
->rtl8168u_unit_lock
);
832 handle_request(LIBBASE
, io
);
837 RTLD(bug("[%s] RTL8168_Schedular: Handle incomming signal.\n", taskSelf
->tc_Node
.ln_Name
))
838 /* Handle incoming signals */
848 static struct AddressRange
*FindMulticastRange(LIBBASETYPEPTR LIBBASE
, struct RTL8168Unit
*unit
,
849 ULONG lower_bound_left
, UWORD lower_bound_right
, ULONG upper_bound_left
, UWORD upper_bound_right
)
851 struct AddressRange
*range
, *tail
;
854 range
= (APTR
)unit
->rtl8168u_multicast_ranges
.mlh_Head
;
855 tail
= (APTR
)&unit
->rtl8168u_multicast_ranges
.mlh_Tail
;
857 while((range
!= tail
) && !found
)
859 if((lower_bound_left
== range
->lower_bound_left
) &&
860 (lower_bound_right
== range
->lower_bound_right
) &&
861 (upper_bound_left
== range
->upper_bound_left
) &&
862 (upper_bound_right
== range
->upper_bound_right
))
865 range
= (APTR
)range
->node
.mln_Succ
;
874 BOOL
AddMulticastRange(LIBBASETYPEPTR LIBBASE
, struct RTL8168Unit
*unit
, const UBYTE
*lower_bound
,
875 const UBYTE
*upper_bound
)
877 struct AddressRange
*range
;
878 ULONG lower_bound_left
, upper_bound_left
;
879 UWORD lower_bound_right
, upper_bound_right
;
881 lower_bound_left
= AROS_BE2LONG(*((ULONG
*)lower_bound
));
882 lower_bound_right
= AROS_BE2WORD(*((UWORD
*)(lower_bound
+ 4)));
883 upper_bound_left
= AROS_BE2LONG(*((ULONG
*)upper_bound
));
884 upper_bound_right
= AROS_BE2WORD(*((UWORD
*)(upper_bound
+ 4)));
886 range
= FindMulticastRange(LIBBASE
, unit
, lower_bound_left
, lower_bound_right
,
887 upper_bound_left
, upper_bound_right
);
893 range
= AllocMem(sizeof(struct AddressRange
), MEMF_PUBLIC
);
896 range
->lower_bound_left
= lower_bound_left
;
897 range
->lower_bound_right
= lower_bound_right
;
898 range
->upper_bound_left
= upper_bound_left
;
899 range
->upper_bound_right
= upper_bound_right
;
900 range
->add_count
= 1;
903 AddTail((APTR
)&unit
->rtl8168u_multicast_ranges
, (APTR
)range
);
906 if (unit
->rtl8168u_range_count
++ == 0)
908 unit
->rtl8168u_flags
|= IFF_ALLMULTI
;
909 unit
->set_multicast(unit
);
914 return range
!= NULL
;
917 BOOL
RemMulticastRange(LIBBASETYPEPTR LIBBASE
, struct RTL8168Unit
*unit
, const UBYTE
*lower_bound
, const UBYTE
*upper_bound
)
919 struct AddressRange
*range
;
920 ULONG lower_bound_left
, upper_bound_left
;
921 UWORD lower_bound_right
, upper_bound_right
;
923 lower_bound_left
= AROS_BE2LONG(*((ULONG
*)lower_bound
));
924 lower_bound_right
= AROS_BE2WORD(*((UWORD
*)(lower_bound
+ 4)));
925 upper_bound_left
= AROS_BE2LONG(*((ULONG
*)upper_bound
));
926 upper_bound_right
= AROS_BE2WORD(*((UWORD
*)(upper_bound
+ 4)));
928 range
= FindMulticastRange(LIBBASE
, unit
, lower_bound_left
, lower_bound_right
,
929 upper_bound_left
, upper_bound_right
);
933 if(--range
->add_count
== 0)
938 FreeMem(range
, sizeof(struct AddressRange
));
940 if (--unit
->rtl8168u_range_count
== 0)
942 unit
->rtl8168u_flags
&= ~IFF_ALLMULTI
;
943 unit
->set_multicast(unit
);
947 return range
!= NULL
;
951 * Create new RTL8168 ethernet device unit
953 struct RTL8168Unit
*CreateUnit(struct RTL8168Base
*RTL8168DeviceBase
, OOP_Object
*pciDevice
, IPTR CardRevision
)
955 struct RTL8168Unit
*unit
;
959 #if defined(RTL_DEBUG)
962 /* TODO: Get option to debug from somewhere .. */
963 BOOL doDebug
= FALSE
;
968 bug("[rtl8168] CreateUnit()\n");
971 if ((unit
= AllocMem(sizeof(struct RTL8168Unit
), MEMF_PUBLIC
| MEMF_CLEAR
)) != NULL
)
973 IPTR mmiobase
, mmiolen
, type
;
976 BOOL mmioerror
= FALSE
;
979 unit
->rtl8168u_flags
|= IFF_DEBUG
;
981 unit
->rtl8168u_UnitNum
= RTL8168DeviceBase
->rtl8168b_UnitCount
++;
983 unit
->rtl8168u_Sana2Info
.HardwareType
= S2WireType_Ethernet
;
984 unit
->rtl8168u_Sana2Info
.MTU
= ETH_MTU
;
985 unit
->rtl8168u_Sana2Info
.AddrFieldSize
= 8 * ETH_ADDRESSSIZE
;
987 unit
->rtl8168u_intr_mask
= SYSErr
| LinkChg
| RxDescUnavail
| TxErr
| TxOK
| RxErr
| RxOK
;
989 if ((unit
->rtl8168u_name
= AllocVec(8 + (unit
->rtl8168u_UnitNum
/10) + 2, MEMF_CLEAR
|MEMF_PUBLIC
)) == NULL
)
991 FreeMem(unit
, sizeof(struct RTL8168Unit
));
994 sprintf((char *)unit
->rtl8168u_name
, "rtl8168.%d", unit
->rtl8168u_UnitNum
);
996 RTLD(bug("[rtl8168] CreateUnit: Unit allocated @ 0x%p\n", unit
))
998 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Driver
, (APTR
)&driver
);
1000 unit
->rtl8168u_device
= RTL8168DeviceBase
;
1001 unit
->rtl8168u_PCIDevice
= pciDevice
;
1002 unit
->rtl8168u_PCIDriver
= driver
;
1004 unit
->rtl8168u_mtu
= unit
->rtl8168u_Sana2Info
.MTU
;
1006 InitSemaphore(&unit
->rtl8168u_unit_lock
);
1007 NEWLIST(&unit
->rtl8168u_Openers
);
1008 NEWLIST(&unit
->rtl8168u_multicast_ranges
);
1009 NEWLIST(&unit
->rtl8168u_type_trackers
);
1011 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_INTLine
, &unit
->rtl8168u_IRQ
);
1012 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Base0
, (IPTR
*)&unit
->rtl8168u_BaseIO
);
1013 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Base2
, &mmiobase
);
1014 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Size2
, &mmiolen
);
1015 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Type2
, &type
);
1017 RTLD(bug("[%s] CreateUnit: INT:%d, base0:0x%p, base2:0x%p, size2:%d\n", unit
->rtl8168u_name
,
1018 unit
->rtl8168u_IRQ
, unit
->rtl8168u_BaseIO
,
1021 if (type
& ADDRF_IO
)
1023 RTLD(bug("[%s] CreateUnit: MMIO Region of wrong type!\n", unit
->rtl8168u_name
))
1027 if (mmiolen
< R8168_REGS_SIZE
)
1029 RTLD(bug("[%s] CreateUnit: Invalid MMIO Reg size (%d, expected %d)\n", unit
->rtl8168u_name
,
1037 FreeMem(unit
->rtl8168u_name
, 8 + (unit
->rtl8168u_UnitNum
/10) + 2);
1038 FreeMem(unit
, sizeof(struct RTL8168Unit
));
1042 /* TODO: how do we set memory write invalidate for PCI devices on AROS? */
1044 unit
->rtl8168u_SizeMem
= R8168_REGS_SIZE
;
1045 unit
->rtl8168u_BaseMem
= HIDD_PCIDriver_MapPCI(driver
, (APTR
)mmiobase
, unit
->rtl8168u_SizeMem
);
1047 if (unit
->rtl8168u_BaseMem
!= NULL
)
1049 struct TagItem attrs
[] = {
1050 { aHidd_PCIDevice_isIO
, TRUE
},
1051 { aHidd_PCIDevice_isMEM
, TRUE
},
1052 { aHidd_PCIDevice_isMaster
, TRUE
},
1055 OOP_SetAttrs(pciDevice
, (struct TagItem
*)&attrs
);
1057 RTLD(bug("[%s] CreateUnit: PCI_BaseMem @ 0x%p\n", unit
->rtl8168u_name
, unit
->rtl8168u_BaseMem
))
1059 unit
->rtl8168u_DelayPort
.mp_SigBit
= SIGB_SINGLE
;
1060 unit
->rtl8168u_DelayPort
.mp_Flags
= PA_SIGNAL
;
1061 unit
->rtl8168u_DelayPort
.mp_SigTask
= FindTask(NULL
);
1062 unit
->rtl8168u_DelayPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
1063 NEWLIST(&unit
->rtl8168u_DelayPort
.mp_MsgList
);
1065 unit
->rtl8168u_DelayReq
.tr_node
.io_Message
.mn_ReplyPort
= &unit
->rtl8168u_DelayPort
;
1066 unit
->rtl8168u_DelayReq
.tr_node
.io_Message
.mn_Length
= sizeof(struct timerequest
);
1068 OpenDevice((STRPTR
)"timer.device", UNIT_MICROHZ
, (struct IORequest
*)&unit
->rtl8168u_DelayReq
, 0);
1070 if ((unit
->rtl8168u_priv
= AllocMem(sizeof(struct rtl8168_priv
), MEMF_PUBLIC
|MEMF_CLEAR
)) != NULL
)
1072 unit
->rtl8168u_priv
->pci_dev
= unit
;
1073 InitSemaphore(&unit
->rtl8168u_priv
->lock
);
1076 struct Message
*msg
;
1078 unit
->rtl8168u_irqhandler
.is_Node
.ln_Type
= NT_INTERRUPT
;
1079 unit
->rtl8168u_irqhandler
.is_Node
.ln_Pri
= 100;
1080 unit
->rtl8168u_irqhandler
.is_Node
.ln_Name
= LIBBASE
->rtl8168b_Device
.dd_Library
.lib_Node
.ln_Name
;
1081 unit
->rtl8168u_irqhandler
.is_Code
= (VOID_FUNC
)RTL8168_IntHandlerF
;
1082 unit
->rtl8168u_irqhandler
.is_Data
= unit
;
1084 unit
->rtl8168u_touthandler
.is_Node
.ln_Type
= NT_INTERRUPT
;
1085 unit
->rtl8168u_touthandler
.is_Node
.ln_Pri
= 100;
1086 unit
->rtl8168u_touthandler
.is_Node
.ln_Name
= LIBBASE
->rtl8168b_Device
.dd_Library
.lib_Node
.ln_Name
;
1087 unit
->rtl8168u_touthandler
.is_Code
= (VOID_FUNC
)RTL8168_TimeoutHandlerF
;
1088 unit
->rtl8168u_touthandler
.is_Data
= unit
;
1090 unit
->rtl8168u_rx_int
.is_Node
.ln_Type
= NT_INTERRUPT
;
1091 unit
->rtl8168u_rx_int
.is_Node
.ln_Name
= unit
->rtl8168u_name
;
1092 //unit->rtl8168u_rx_int.is_Code = (VOID_FUNC)RTL8168_RX_IntF;
1093 unit
->rtl8168u_rx_int
.is_Data
= unit
;
1095 unit
->rtl8168u_tx_int
.is_Node
.ln_Type
= NT_INTERRUPT
;
1096 unit
->rtl8168u_tx_int
.is_Node
.ln_Name
= unit
->rtl8168u_name
;
1097 unit
->rtl8168u_tx_int
.is_Code
= (VOID_FUNC
)RTL8168_TX_IntF
;
1098 unit
->rtl8168u_tx_int
.is_Data
= unit
;
1100 for (i
=0; i
< REQUEST_QUEUE_COUNT
; i
++)
1102 struct MsgPort
*port
= AllocMem(sizeof(struct MsgPort
), MEMF_PUBLIC
| MEMF_CLEAR
);
1103 unit
->rtl8168u_request_ports
[i
] = port
;
1105 if (port
== NULL
) success
= FALSE
;
1109 NEWLIST(&port
->mp_MsgList
);
1110 port
->mp_Flags
= PA_IGNORE
;
1111 port
->mp_SigTask
= &unit
->rtl8168u_tx_int
;
1115 unit
->rtl8168u_request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
1119 struct RTL8168Startup
*sm_UD
;
1122 if ((sm_UD
= AllocMem(sizeof(struct RTL8168Startup
), MEMF_PUBLIC
| MEMF_CLEAR
)) != NULL
)
1124 sprintf((char *)tmpbuff
, RTL8168_TASK_NAME
, unit
->rtl8168u_name
);
1126 sm_UD
->rtl8168sm_SyncPort
= CreateMsgPort();
1127 sm_UD
->rtl8168sm_Unit
= unit
;
1129 rtl8168nic_get_functions(unit
);
1131 unit
->rtl8168u_Process
= CreateNewProcTags(
1132 NP_Entry
, (IPTR
)RTL8168_Schedular
,
1134 NP_Synchronous
, FALSE
,
1136 NP_UserData
, (IPTR
)sm_UD
,
1137 NP_StackSize
, 140960,
1140 WaitPort(sm_UD
->rtl8168sm_SyncPort
);
1141 msg
= GetMsg(sm_UD
->rtl8168sm_SyncPort
);
1143 DeleteMsgPort(sm_UD
->rtl8168sm_SyncPort
);
1144 FreeMem(sm_UD
, sizeof(struct RTL8168Startup
));
1146 RTLD(bug("[%s] CreateUnit: Device Initialised. Unit %d @ %p\n", unit
->rtl8168u_name
, unit
->rtl8168u_UnitNum
, unit
))
1152 RTLD(bug("[%s] ERRORS occured during Device setup - ABORTING\n", unit
->rtl8168u_name
))
1159 RTLD(bug("[rtl8168] PANIC! Couldn't get MMIO area. Aborting\n"))
1164 bug("[rtl8168] CreateUnit: Failed to Allocate Unit storage!\n");
1167 DeleteUnit(RTL8168DeviceBase
, unit
);
1172 * DeleteUnit - removes selected unit. Frees all resources and structures.
1174 * The caller should be sure, that given unit is really ready to be freed.
1177 void DeleteUnit(struct RTL8168Base
*RTL8168DeviceBase
, struct RTL8168Unit
*Unit
)
1182 if (Unit
->rtl8168u_Process
)
1184 Signal(&Unit
->rtl8168u_Process
->pr_Task
, Unit
->rtl8168u_signal_0
);
1187 for (i
=0; i
< REQUEST_QUEUE_COUNT
; i
++)
1189 if (Unit
->rtl8168u_request_ports
[i
] != NULL
)
1190 FreeMem(Unit
->rtl8168u_request_ports
[i
], sizeof(struct MsgPort
));
1192 Unit
->rtl8168u_request_ports
[i
] = NULL
;
1195 if (Unit
->rtl8168u_priv
)
1197 FreeMem(Unit
->rtl8168u_priv
, sizeof(struct rtl8168_priv
));
1198 Unit
->rtl8168u_priv
= NULL
;
1201 if (Unit
->rtl8168u_BaseMem
)
1203 HIDD_PCIDriver_UnmapPCI(Unit
->rtl8168u_PCIDriver
,
1204 (APTR
)Unit
->rtl8168u_BaseMem
,
1205 Unit
->rtl8168u_SizeMem
);
1208 FreeMem(Unit
, sizeof(struct RTL8168Unit
));