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,
24 #include <exec/types.h>
25 #include <exec/resident.h>
27 #include <exec/ports.h>
28 #include <exec/errors.h>
32 #include <devices/sana2.h>
33 #include <devices/sana2specialstats.h>
34 #include <devices/newstyle.h>
35 #include <devices/timer.h>
37 #include <utility/utility.h>
38 #include <utility/tagitem.h>
39 #include <utility/hooks.h>
41 #include <proto/exec.h>
42 #include <proto/dos.h>
43 #include <proto/oop.h>
44 #include <proto/timer.h>
45 #include <proto/utility.h>
52 #include LC_LIBDEFS_FILE
55 * Report incoming events to all hyphotetical event receivers
57 VOID
ReportEvents(struct RTL8139Base
*RTL8139DeviceBase
, struct RTL8139Unit
*unit
, ULONG events
)
59 struct IOSana2Req
*request
, *tail
, *next_request
;
62 list
= &unit
->rtl8139u_request_ports
[EVENT_QUEUE
]->mp_MsgList
;
63 next_request
= (APTR
)list
->lh_Head
;
64 tail
= (APTR
)&list
->lh_Tail
;
66 /* Go through list of event listeners. If send messages to receivers if event found */
68 while(next_request
!= tail
)
70 request
= next_request
;
71 next_request
= (APTR
)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
73 if((request
->ios2_WireError
&events
) != 0)
75 request
->ios2_WireError
= events
;
76 Remove((APTR
)request
);
77 ReplyMsg((APTR
)request
);
85 struct TypeStats
*FindTypeStats(struct RTL8139Base
*RTL8139DeviceBase
, struct RTL8139Unit
*unit
,
86 struct MinList
*list
, ULONG packet_type
)
88 struct TypeStats
*stats
, *tail
;
91 stats
= (APTR
)list
->mlh_Head
;
92 tail
= (APTR
)&list
->mlh_Tail
;
94 while(stats
!= tail
&& !found
)
96 if(stats
->packet_type
== packet_type
)
99 stats
= (APTR
)stats
->node
.mln_Succ
;
108 void FlushUnit(LIBBASETYPEPTR LIBBASE
, struct RTL8139Unit
*unit
, UBYTE last_queue
, BYTE error
)
110 struct IORequest
*request
;
112 struct Opener
*opener
, *tail
;
114 RTLD(bug("[%s] unit.FlushUnit\n", unit
->rtl8139u_name
))
116 /* Abort queued operations */
118 for (i
=0; i
<= last_queue
; i
++)
120 while ((request
= (APTR
)GetMsg(unit
->rtl8139u_request_ports
[i
])) != NULL
)
122 request
->io_Error
= IOERR_ABORTED
;
123 ReplyMsg((struct Message
*)request
);
127 opener
= (APTR
)unit
->rtl8139u_Openers
.mlh_Head
;
128 tail
= (APTR
)unit
->rtl8139u_Openers
.mlh_Tail
;
130 /* Flush every opener's read queue */
132 while(opener
!= tail
)
134 while ((request
= (APTR
)GetMsg(&opener
->read_port
)) != NULL
)
136 request
->io_Error
= error
;
137 ReplyMsg((struct Message
*)request
);
139 opener
= (struct Opener
*)opener
->node
.mln_Succ
;
143 /* Interrupt Rx Support Function ..
144 * It's duty is to iterate throgh RX queue searching for new packets.
146 void RTL8139_RX_Process(struct RTL8139Unit
*unit
)
148 struct RTL8139Base
*RTL8139DeviceBase
= unit
->rtl8139u_device
;
149 struct fe_priv
*np
= unit
->rtl8139u_fe_priv
;
150 UBYTE
*base
= unit
->rtl8139u_BaseMem
;
152 struct TypeStats
*tracker
;
154 struct Opener
*opener
, *opener_tail
;
155 struct IOSana2Req
*request
, *request_tail
;
156 BOOL accepted
, is_orphan
;
158 RTLD(bug("[%s] RTL8139_RX_Process() !!!!\n", unit
->rtl8139u_name
))
160 while((BYTEIN(base
+ RTLr_ChipCmd
) & RxBufEmpty
) == 0)
162 UWORD len
= 0, overspill
= 0;
163 struct eth_frame
*frame
;
165 unsigned short cur_rx
= np
->cur_rx
;
166 unsigned int ring_offset
= cur_rx
% np
->rx_buf_len
;
167 unsigned long rx_status
= *(unsigned long *)(np
->rx_buffer
+ ring_offset
);
168 unsigned int rx_size
= rx_status
>> 16;
170 np
->cur_rx
= (unsigned short)(cur_rx
+ rx_size
+ ETH_CRCSIZE
+ 3) & ~3;
171 WORDOUT(base
+ RTLr_RxBufPtr
, np
->cur_rx
- 16);
173 RTLD(bug("[%s] RTL8139_RX_Process: RecieveBuffers @ 0x%p\n",
174 unit
->rtl8139u_name
, np
->rx_buffer
))
176 RTLD(bug("[%s] RTL8139_RX_Process: Rx = %d [offset=%4.4x, Status=%8.8x Size=%d]\n",
177 unit
->rtl8139u_name
, cur_rx
, ring_offset
, rx_status
, rx_size
))
179 if (rx_status
& (RxBadSymbol
| RxRunt
| RxTooLong
| RxCRCErr
| RxBadAlign
))
181 RTLD(bug("[%s] RTL8139_RX_Process: Ethernet frame had errors, Status %8.8x\n",
182 unit
->rtl8139u_name
, rx_status
))
184 if (rx_status
== 0xffffffff)
186 RTLD(bug("[%s] RTL8139_RX_Process: Invalid Recieve Status\n", unit
->rtl8139u_name
))
190 if (rx_status
& RxTooLong
)
192 RTLD(bug("[%s] RTL8139_RX_Process: Oversized Ethernet Frame\n", unit
->rtl8139u_name
))
195 /* Reset the reciever */
197 BYTEOUT(base
+ RTLr_ChipCmd
, CmdTxEnb
);
199 rtl8139nic_set_rxmode(unit
);
200 BYTEOUT(base
+ RTLr_ChipCmd
, CmdRxEnb
| CmdTxEnb
);
202 else if (rx_status
& RxStatusOK
)
204 len
= rx_size
- ETH_CRCSIZE
;
205 frame
= (APTR
)(np
->rx_buffer
+ ring_offset
+ ETH_CRCSIZE
);
206 RTLD(bug("[%s] RTL8139_RX_Process: frame @ %p, len=%d\n", unit
->rtl8139u_name
, frame
, len
))
208 /* got a valid packet - forward it to the network core */
211 if (ring_offset
+ rx_size
> np
->rx_buf_len
)
213 overspill
= (ring_offset
+ rx_size
) - np
->rx_buf_len
;
214 RTLD(bug("[%s] RTL8139_RX_Process: WRAPPED Frame! (%d bytes overspill)\n", unit
->rtl8139u_name
, overspill
))
215 len
= len
- overspill
;
216 /* TODO: We need to copy the wrapped buffer into a temp buff to pass to listeners! */
220 for (j
=0; j
<64; j
++) {
224 bug(" %02x", ((unsigned char*)frame
)[j
]);
228 /* Check for address validity */
229 if(AddressFilter(LIBBASE
, unit
, frame
->eth_packet_dest
))
231 /* Packet is addressed to this driver */
232 packet_type
= AROS_BE2WORD(frame
->eth_packet_type
);
233 RTLD(bug("[%s] RTL8139_RX_Process: Packet IP accepted with type = %d\n", unit
->rtl8139u_name
, packet_type
))
235 opener
= (APTR
)unit
->rtl8139u_Openers
.mlh_Head
;
236 opener_tail
= (APTR
)&unit
->rtl8139u_Openers
.mlh_Tail
;
238 /* Offer packet to every opener */
239 while(opener
!= opener_tail
)
241 request
= (APTR
)opener
->read_port
.mp_MsgList
.lh_Head
;
242 request_tail
= (APTR
)&opener
->read_port
.mp_MsgList
.lh_Tail
;
245 /* Offer packet to each request until it's accepted */
246 while((request
!= request_tail
) && !accepted
)
248 if((request
->ios2_PacketType
== packet_type
)
249 || ((request
->ios2_PacketType
<= ETH_MTU
)
250 && (packet_type
<= ETH_MTU
)))
252 RTLD(bug("[%s] RTL8139_RX_Process: copy packet for opener ..\n", unit
->rtl8139u_name
))
253 CopyPacket(LIBBASE
, unit
, request
, len
, packet_type
, frame
);
256 request
= (struct IOSana2Req
*)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
264 opener
= (APTR
)opener
->node
.mln_Succ
;
267 /* If packet was unwanted, give it to S2_READORPHAN request */
270 unit
->rtl8139u_stats
.UnknownTypesReceived
++;
272 if(!IsMsgPortEmpty(unit
->rtl8139u_request_ports
[ADOPT_QUEUE
]))
274 CopyPacket(LIBBASE
, unit
,
275 (APTR
)unit
->rtl8139u_request_ports
[ADOPT_QUEUE
]->
276 mp_MsgList
.lh_Head
, len
, packet_type
, frame
);
277 RTLD(bug("[%s] RTL8139_RX_Process: packet copied to orphan queue\n", unit
->rtl8139u_name
))
281 /* Update remaining statistics */
282 tracker
= FindTypeStats(LIBBASE
, unit
, &unit
->rtl8139u_type_trackers
, packet_type
);
286 tracker
->stats
.PacketsReceived
++;
287 tracker
->stats
.BytesReceived
+= len
;
290 unit
->rtl8139u_stats
.PacketsReceived
++;
294 RTLD(bug("[%s] RTL8139_RX_Process: Rx Packet Processing complete\n", unit
->rtl8139u_name
))
300 * Interrupt generated by Cause() to push new packets into the NIC interface
302 static AROS_INTH1(RTL8139_TX_IntF
, struct RTL8139Unit
*, unit
)
306 struct fe_priv
*np
= unit
->rtl8139u_fe_priv
;
307 struct RTL8139Base
*RTL8139DeviceBase
= unit
->rtl8139u_device
;
309 BOOL proceed
= FALSE
; /* Fails by default */
312 RTLD(bug("[%s] RTL8139_TX_IntF()\n", unit
->rtl8139u_name
))
314 /* send packet only if there is free space on tx queue. Otherwise do nothing */
315 if (np
->tx_current
- np
->tx_dirty
< NUM_TX_DESC
)
317 UWORD packet_size
, data_size
;
318 struct IOSana2Req
*request
;
319 struct Opener
*opener
;
323 struct MsgPort
*port
;
324 struct TypeStats
*tracker
;
326 proceed
= TRUE
; /* Success by default */
327 UBYTE
*base
= (UBYTE
*) unit
->rtl8139u_BaseMem
;
328 port
= unit
->rtl8139u_request_ports
[WRITE_QUEUE
];
330 /* Still no error and there are packets to be sent? */
331 while(proceed
&& (!IsMsgPortEmpty(port
)))
333 nr
= np
->tx_current
% NUM_TX_DESC
;
336 request
= (APTR
)port
->mp_MsgList
.lh_Head
;
337 data_size
= packet_size
= request
->ios2_DataLength
;
339 opener
= (APTR
)request
->ios2_BufferManagement
;
341 np
->tx_pbuf
[nr
] = np
->tx_buf
[nr
];
342 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
344 packet_size
+= ETH_PACKET_DATA
;
345 CopyMem(request
->ios2_DstAddr
,
346 &((struct eth_frame
*) np
->tx_buf
[nr
])->eth_packet_dest
,
348 CopyMem(unit
->rtl8139u_dev_addr
,
349 &((struct eth_frame
*) np
->tx_buf
[nr
])->eth_packet_source
,
351 ((struct eth_frame
*)np
->tx_buf
[nr
])->eth_packet_type
= AROS_WORD2BE(request
->ios2_PacketType
);
353 buffer
= (UBYTE
*)&((struct eth_frame
*) (IPTR
) np
->tx_buf
[nr
])->eth_packet_data
;
357 buffer
= np
->tx_buf
[nr
];
360 if (packet_size
< TX_BUF_SIZE
)
362 memset(buffer
, 0, TX_BUF_SIZE
- packet_size
);
365 if (!opener
->tx_function(buffer
, request
->ios2_Data
, data_size
))
367 error
= S2ERR_NO_RESOURCES
;
368 wire_error
= S2WERR_BUFF_ERROR
;
369 ReportEvents(LIBBASE
, unit
,
370 S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
|
374 /* Now the packet is already in TX buffer, update flags for NIC */
379 RTLD(bug("[%s] RTL8139_TX_IntF: packet %d @ %p [type = %d] queued for transmission.", unit
->rtl8139u_name
, nr
, np
->tx_buf
[nr
], AROS_BE2WORD(((struct eth_frame
*)np
->tx_buf
[nr
])->eth_packet_type
)))
382 for (j
=0; j
<64; j
++) {
385 bug(" %02x", ((unsigned char*)np
->tx_buf
[nr
])[j
]);
392 /* Set the ring details for the packet */
393 LONGOUT(base
+ RTLr_TxAddr0
+ (nr
<< 2), (IPTR
)np
->tx_buf
[nr
]);
394 LONGOUT(base
+ RTLr_TxStatus0
+ (nr
<< 2), np
->tx_flag
|
395 (packet_size
>= ETH_ZLEN
?
396 packet_size
: ETH_ZLEN
));
400 request
->ios2_Req
.io_Error
= error
;
401 request
->ios2_WireError
= wire_error
;
403 Remove((APTR
)request
);
405 ReplyMsg((APTR
)request
);
407 /* Update statistics */
410 unit
->rtl8139u_stats
.PacketsSent
++;
412 tracker
= FindTypeStats(LIBBASE
, unit
, &unit
->rtl8139u_type_trackers
, request
->ios2_PacketType
);
416 tracker
->stats
.PacketsSent
++;
417 tracker
->stats
.BytesSent
+= packet_size
;
424 * If we've just run out of free space on the TX queue, stop
425 * it and give up pushing further frames */
426 if (np
->tx_current
- np
->tx_dirty
>= NUM_TX_DESC
)
428 RTLD(bug("[%s] output queue full!. Stopping [count = %d, NUM_TX_DESC = %d\n", unit
->rtl8139u_name
, try_count
, NUM_TX_DESC
))
434 /* Was there success? Enable incoming of new packets */
437 unit
->rtl8139u_request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
441 unit
->rtl8139u_request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_IGNORE
;
451 * Handle timeouts and other strange cases
453 static AROS_INTH1(RTL8139_TimeoutHandlerF
,struct RTL8139Unit
*, unit
)
458 struct Device
*TimerBase
= unit
->rtl8139u_TimerSlowReq
->tr_node
.io_Device
;
461 //RTLD(bug("[%s] RTL8139_TimeoutHandlerF()\n", unit->rtl8139u_name))
464 * If timeout timer is expected, and time elapsed - regenerate the
467 if (unit
->rtl8139u_toutNEED
&& (CmpTime(&time
, &unit
->rtl8139u_toutPOLL
) < 0))
469 unit
->rtl8139u_toutNEED
= FALSE
;
470 //Cause(&unit->rtl8139u_tx_end_int);
479 * Interrupt handler called whenever RTL8139 NIC interface generates interrupt.
481 * Please note, that although multicast support could be done on interface
482 * basis, it is done in this function as result of quick integration of both
483 * the forcedeth driver (IFF_ALLMULTI flag) and etherlink3 driver (AddressMatch
486 static AROS_INTH1(RTL8139_IntHandlerF
, struct RTL8139Unit
*, unit
)
490 struct fe_priv
*np
= unit
->rtl8139u_fe_priv
;
491 UBYTE
*base
= (UBYTE
*) unit
->rtl8139u_BaseMem
;
492 unsigned int link_changed
, CSCRval
;
493 int interrupt_work
= 20;
495 RTLD(bug("[%s] RTL8139_IntHandlerF()!!!!!!!\n", unit
->rtl8139u_name
))
499 UWORD status
= WORDIN(base
+ RTLr_IntrStatus
);
501 if (status
& RxUnderrun
)
503 CSCRval
= WORDIN(base
+ RTLr_CSCR
);
504 link_changed
= (CSCRval
& CSCR_LinkChangeBit
);
506 RTLD(bug("[%s] RTL8139_IntHandlerF: Link Change : %d\n", unit
->rtl8139u_name
, link_changed
))
507 /* TODO: Disable/Enable interface on link change */
509 if (CSCRval
& CSCR_LinkOKBit
) {
511 RTLD(bug("[%s] RTL8139_IntHandlerF: Link Change : Link UP\n", unit
->rtl8139u_name
))
513 BYTEOUT(base
+ RTLr_ChipCmd
, CmdTxEnb
);
514 rtl8139nic_set_rxmode(unit
); // Reset the multicast list
515 BYTEOUT(base
+ RTLr_ChipCmd
, CmdRxEnb
| CmdTxEnb
);
516 unit
->rtl8139u_flags
|= IFF_UP
;
519 RTLD(bug("[%s] RTL8139_IntHandlerF: Link Change : Link DOWN\n", unit
->rtl8139u_name
))
521 unit
->rtl8139u_flags
&= ~IFF_UP
;
525 WORDOUT(base
+ RTLr_IntrStatus
, status
);
527 if ((status
& (RxOK
| RxErr
| RxUnderrun
| RxOverflow
| RxFIFOOver
| TxOK
| TxErr
| PCIErr
| PCSTimeout
)) == 0)
529 RTLD(bug("[%s] RTL8139_IntHandlerF: No work to process..\n", unit
->rtl8139u_name
))
533 if (status
& (RxOK
| RxErr
| RxUnderrun
| RxOverflow
| RxFIFOOver
)) // Chipset has Received packet(s)
535 RTLD(bug("[%s] RTL8139_IntHandlerF: Packet Reception Attempt detected!\n", unit
->rtl8139u_name
))
536 RTL8139_RX_Process(unit
);
539 if (status
& (TxOK
| TxErr
)) // Chipset has attempted to Send packet(s)
541 RTLD(bug("[%s] RTL8139_IntHandlerF: Packet Transmition Attempt detected!\n", unit
->rtl8139u_name
))
542 unsigned int dirty_tx
= np
->tx_dirty
;
544 while (np
->tx_current
- dirty_tx
> 0)
546 int entry
= dirty_tx
% NUM_TX_DESC
;
548 ULONG txstatus
= LONGIN(base
+ RTLr_TxStatus0
+ (entry
<< 2));
550 // Still transmitting
551 if (!(txstatus
& (TxStatOK
| TxUnderrun
| TxAborted
))) break;
553 // N.B: TxCarrierLost is always asserted at 100mbps.
554 if (txstatus
& (TxOutOfWindow
| TxAborted
))
556 RTLD(bug("[%s] RTL8139_IntHandlerF: Packet %d Transmition Error! Tx status %8.8x\n", unit
->rtl8139u_name
, entry
, txstatus
))
558 if (txstatus
& TxAborted
)
560 LONGOUT(base
+ RTLr_TxConfig
, TX_DMA_BURST
<< 8);
565 if (txstatus
& TxUnderrun
)
567 RTLD(bug("[%s] RTL8139_IntHandlerF: Packet %d Transmition Underrun Error! Adjusting flags\n", unit
->rtl8139u_name
, entry
))
569 if (np
->tx_flag
< 0x00300000)
571 np
->tx_flag
+= 0x00020000;
575 np
->tx_pbuf
[entry
] = NULL
;
578 np
->tx_dirty
= dirty_tx
;
580 // Restart transmissions if they had stopped due to ring being full
581 if(unit
->rtl8139u_request_ports
[WRITE_QUEUE
]->mp_Flags
== PA_IGNORE
)
582 Cause(&unit
->rtl8139u_tx_int
);
585 if (status
& (PCIErr
| PCSTimeout
| TxUnderrun
| RxOverflow
| RxFIFOOver
| TxErr
| RxErr
)) // Chipset has Reported an ERROR
587 RTLD(bug("[%s] RTL8139_IntHandlerF: ERROR Detected\n", unit
->rtl8139u_name
))
588 if (status
== 0xffff)
590 break; // Missing Chip!
594 if (--interrupt_work
< 0)
596 RTLD(bug("[%s] RTL8139_IntHandlerF: MAX interrupt work reached.\n", unit
->rtl8139u_name
))
597 WORDOUT(base
+ RTLr_IntrStatus
, 0xffff);
607 VOID
CopyPacket(struct RTL8139Base
*RTL8139DeviceBase
, struct RTL8139Unit
*unit
,
608 struct IOSana2Req
*request
, UWORD packet_size
, UWORD packet_type
,
609 struct eth_frame
*buffer
)
611 struct Opener
*opener
;
612 BOOL filtered
= FALSE
;
614 const UBYTE broadcast
[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
616 RTLD(bug("[%s] CopyPacket(packet @ %x, len = %d)\n", unit
->rtl8139u_name
, buffer
, packet_size
))
618 /* Set multicast and broadcast flags */
620 request
->ios2_Req
.io_Flags
&= ~(SANA2IOF_BCAST
| SANA2IOF_MCAST
);
621 if (memcmp(buffer
->eth_packet_dest
, broadcast
, 6) == 0)
623 request
->ios2_Req
.io_Flags
|= SANA2IOF_BCAST
;
624 RTLD(bug("[%s] CopyPacket: BROADCAST Flag set\n", unit
->rtl8139u_name
))
626 else if((buffer
->eth_packet_dest
[0] & 0x1) != 0)
628 request
->ios2_Req
.io_Flags
|= SANA2IOF_MCAST
;
629 RTLD(bug("[%s] CopyPacket: MULTICAST Flag set\n", unit
->rtl8139u_name
))
632 /* Set source and destination addresses and packet type */
633 CopyMem(buffer
->eth_packet_source
, request
->ios2_SrcAddr
, ETH_ADDRESSSIZE
);
634 CopyMem(buffer
->eth_packet_dest
, request
->ios2_DstAddr
, ETH_ADDRESSSIZE
);
635 request
->ios2_PacketType
= packet_type
;
637 /* Adjust for cooked packet request */
639 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
641 packet_size
-= ETH_PACKET_DATA
;
642 ptr
= (UBYTE
*)&buffer
->eth_packet_data
[0];
646 ptr
= (UBYTE
*)buffer
;
649 request
->ios2_DataLength
= packet_size
;
651 RTLD(bug("[%s] CopyPacket: packet @ %x (%d bytes)\n", unit
->rtl8139u_name
, ptr
, packet_size
))
655 opener
= request
->ios2_BufferManagement
;
656 if((request
->ios2_Req
.io_Command
== CMD_READ
) &&
657 (opener
->filter_hook
!= NULL
))
658 if(!CallHookPkt(opener
->filter_hook
, request
, ptr
))
660 RTLD(bug("[%s] CopyPacket: packet filtered\n", unit
->rtl8139u_name
))
666 /* Copy packet into opener's buffer and reply packet */
667 RTLD(bug("[%s] CopyPacket: opener recieve packet .. ", unit
->rtl8139u_name
))
668 if(!opener
->rx_function(request
->ios2_Data
, ptr
, packet_size
))
670 RTLD(bug("ERROR occured!!\n"))
671 request
->ios2_Req
.io_Error
= S2ERR_NO_RESOURCES
;
672 request
->ios2_WireError
= S2WERR_BUFF_ERROR
;
673 ReportEvents(LIBBASE
, unit
, S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
| S2EVENT_RX
);
677 RTLD(bug("SUCCESS!!\n"))
680 Remove((APTR
)request
);
682 ReplyMsg((APTR
)request
);
683 RTLD(bug("[%s] CopyPacket: opener notified.\n", unit
->rtl8139u_name
))
687 BOOL
AddressFilter(struct RTL8139Base
*RTL8139DeviceBase
, struct RTL8139Unit
*unit
, UBYTE
*address
)
689 struct AddressRange
*range
, *tail
;
694 /* Check whether address is unicast/broadcast or multicast */
696 address_left
= AROS_BE2LONG(*((ULONG
*)address
));
697 address_right
= AROS_BE2WORD(*((UWORD
*)(address
+ 4)));
699 if((address_left
& 0x01000000) != 0 &&
700 !(address_left
== 0xffffffff && address_right
== 0xffff))
702 /* Check if this multicast address is wanted */
704 range
= (APTR
)unit
->rtl8139u_multicast_ranges
.mlh_Head
;
705 tail
= (APTR
)&unit
->rtl8139u_multicast_ranges
.mlh_Tail
;
708 while((range
!= tail
) && !accept
)
710 if((address_left
> range
->lower_bound_left
||
711 (address_left
== range
->lower_bound_left
&&
712 address_right
>= range
->lower_bound_right
)) &&
713 (address_left
< range
->upper_bound_left
||
714 (address_left
== range
->upper_bound_left
&&
715 address_right
<= range
->upper_bound_right
)))
717 range
= (APTR
)range
->node
.mln_Succ
;
721 unit
->rtl8139u_special_stats
[S2SS_ETHERNET_BADMULTICAST
& 0xffff]++;
729 AROS_UFH3(void, RTL8139_Schedular
,
730 AROS_UFHA(STRPTR
, argPtr
, A0
),
731 AROS_UFHA(ULONG
, argSize
, D0
),
732 AROS_UFHA(struct ExecBase
*, SysBase
, A6
))
736 struct Task
*taskSelf
= FindTask(NULL
);
737 struct RTL8139Startup
*sm_UD
= taskSelf
->tc_UserData
;
738 struct RTL8139Unit
*unit
= sm_UD
->rtl8139sm_Unit
;
740 LIBBASETYPEPTR LIBBASE
= unit
->rtl8139u_device
;
741 struct MsgPort
*reply_port
, *input
;
743 RTLD(bug("[%s] RTL8139_Schedular()\n", taskSelf
->tc_Node
.ln_Name
))
744 RTLD(bug("[%s] RTL8139_Schedular: Setting up device '%s'\n", taskSelf
->tc_Node
.ln_Name
, unit
->rtl8139u_name
))
746 if ((reply_port
= CreateMsgPort()) == NULL
)
748 RTLD(bug("[%s] RTL8139_Schedular: Failed to create Reply message port\n", taskSelf
->tc_Node
.ln_Name
))
751 if ((input
= CreateMsgPort()) == NULL
)
753 RTLD(bug("[%s] RTL8139_Schedular: Failed to create Input message port\n", taskSelf
->tc_Node
.ln_Name
))
756 unit
->rtl8139u_input_port
= input
;
758 if ((unit
->rtl8139u_TimerSlowPort
= CreateMsgPort()) != NULL
)
760 unit
->rtl8139u_TimerSlowReq
= (struct timerequest
*)
761 CreateIORequest((struct MsgPort
*)unit
->rtl8139u_TimerSlowPort
, sizeof(struct timerequest
));
763 if (unit
->rtl8139u_TimerSlowReq
)
765 if (!OpenDevice("timer.device", UNIT_VBLANK
,
766 (struct IORequest
*)unit
->rtl8139u_TimerSlowReq
, 0))
768 struct Message
*msg
= AllocVec(sizeof(struct Message
), MEMF_PUBLIC
|MEMF_CLEAR
);
771 RTLD(bug("[%s] RTL8139_Schedular: Got VBLANK unit of timer.device\n", taskSelf
->tc_Node
.ln_Name
))
773 unit
->initialize(unit
);
775 msg
->mn_ReplyPort
= reply_port
;
776 msg
->mn_Length
= sizeof(struct Message
);
778 RTLD(bug("[%s] RTL8139_Schedular: Setup complete. Sending handshake\n", taskSelf
->tc_Node
.ln_Name
))
779 PutMsg(sm_UD
->rtl8139sm_SyncPort
, msg
);
780 WaitPort(reply_port
);
785 RTLD(bug("[%s] RTL8139_Schedular: entering forever loop ... \n", taskSelf
->tc_Node
.ln_Name
))
787 unit
->rtl8139u_signal_0
= AllocSignal(-1);
788 unit
->rtl8139u_signal_1
= AllocSignal(-1);
789 unit
->rtl8139u_signal_2
= AllocSignal(-1);
790 unit
->rtl8139u_signal_3
= AllocSignal(-1);
792 sigset
= 1 << input
->mp_SigBit
|
793 1 << unit
->rtl8139u_signal_0
|
794 1 << unit
->rtl8139u_signal_1
|
795 1 << unit
->rtl8139u_signal_2
|
796 1 << unit
->rtl8139u_signal_3
;
799 ULONG recvd
= Wait(sigset
);
800 if (recvd
& 1 << unit
->rtl8139u_signal_0
)
803 * Shutdown process. Driver should close everything
804 * already and waits for our process to complete. Free
805 * memory allocared here and kindly return.
807 unit
->deinitialize(unit
);
808 CloseDevice((struct IORequest
*)unit
->rtl8139u_TimerSlowReq
);
809 DeleteIORequest((struct IORequest
*)unit
->rtl8139u_TimerSlowReq
);
810 DeleteMsgPort(unit
->rtl8139u_TimerSlowPort
);
811 DeleteMsgPort(input
);
812 DeleteMsgPort(reply_port
);
814 RTLD(bug("[%s] RTL8139_Schedular: Process shutdown.\n", taskSelf
->tc_Node
.ln_Name
))
817 else if (recvd
& (1 << input
->mp_SigBit
))
819 struct IOSana2Req
*io
;
821 /* Handle incoming transactions */
822 while ((io
= (struct IOSana2Req
*)GetMsg(input
))!= NULL
)
824 RTLD(bug("[%s] RTL8139_Schedular: Handle incomming transaction.\n", taskSelf
->tc_Node
.ln_Name
))
825 ObtainSemaphore(&unit
->rtl8139u_unit_lock
);
826 handle_request(LIBBASE
, io
);
831 RTLD(bug("[%s] RTL8139_Schedular: Handle incomming signal.\n", taskSelf
->tc_Node
.ln_Name
))
832 /* Handle incoming signals */
843 * Create new RTL8139 ethernet device unit
845 struct RTL8139Unit
*CreateUnit(struct RTL8139Base
*RTL8139DeviceBase
, OOP_Object
*pciDevice
, ULONG CardCapabilities
, char * CardName
, char * CardChipset
)
847 struct RTL8139Unit
*unit
;
851 #if defined(RTL_DEBUG)
854 /* TODO: Get option to debug from somewhere .. */
855 BOOL doDebug
= FALSE
;
860 bug("[rtl8139] CreateUnit()\n");
863 if ((unit
= AllocMem(sizeof(struct RTL8139Unit
), MEMF_PUBLIC
| MEMF_CLEAR
)) != NULL
)
865 IPTR DeviceID
, base
, len
;
869 unit
->rtl8139u_flags
|= IFF_DEBUG
;
871 unit
->rtl8139u_UnitNum
= RTL8139DeviceBase
->rtl8139b_UnitCount
++;
873 unit
->rtl8139u_Sana2Info
.HardwareType
= S2WireType_Ethernet
;
874 unit
->rtl8139u_Sana2Info
.MTU
= ETH_MTU
;
875 unit
->rtl8139u_Sana2Info
.AddrFieldSize
= 8 * ETH_ADDRESSSIZE
;
877 if ((unit
->rtl8139u_name
= AllocVec(8 + (unit
->rtl8139u_UnitNum
/10) + 2, MEMF_CLEAR
|MEMF_PUBLIC
)) == NULL
)
879 FreeMem(unit
, sizeof(struct RTL8139Unit
));
882 sprintf((char *)unit
->rtl8139u_name
, "rtl8139.%d", (int)unit
->rtl8139u_UnitNum
);
884 RTLD(bug("[rtl8139] CreateUnit: Unit allocated @ 0x%p\n", unit
))
886 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_ProductID
, &DeviceID
);
887 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Driver
, (APTR
)&driver
);
889 unit
->rtl8139u_rtl_cardname
= CardName
;
890 unit
->rtl8139u_rtl_chipname
= CardChipset
;
891 unit
->rtl8139u_rtl_chipcapabilities
= CardCapabilities
;
893 unit
->rtl8139u_device
= RTL8139DeviceBase
;
894 unit
->rtl8139u_DeviceID
= DeviceID
;
895 unit
->rtl8139u_PCIDevice
= pciDevice
;
896 unit
->rtl8139u_PCIDriver
= driver
;
898 unit
->rtl8139u_mtu
= unit
->rtl8139u_Sana2Info
.MTU
;
900 InitSemaphore(&unit
->rtl8139u_unit_lock
);
901 NEWLIST(&unit
->rtl8139u_Openers
);
902 NEWLIST(&unit
->rtl8139u_multicast_ranges
);
903 NEWLIST(&unit
->rtl8139u_type_trackers
);
905 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_INTLine
, &unit
->rtl8139u_IRQ
);
906 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Base1
, &unit
->rtl8139u_BaseIO
);
907 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Base0
, &base
);
908 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Size0
, &len
);
910 RTLD(bug("[%s] CreateUnit: INT:%d, base1:0x%p, base0:0x%p, size0:%d\n", unit
->rtl8139u_name
,
911 unit
->rtl8139u_IRQ
, unit
->rtl8139u_BaseIO
,
914 unit
->rtl8139u_BaseMem
= HIDD_PCIDriver_MapPCI(driver
, (APTR
)base
, len
);
915 unit
->rtl8139u_SizeMem
= len
;
917 if (unit
->rtl8139u_BaseMem
)
919 struct TagItem attrs
[] = {
920 { aHidd_PCIDevice_isIO
, TRUE
},
921 { aHidd_PCIDevice_isMEM
, TRUE
},
922 { aHidd_PCIDevice_isMaster
, TRUE
},
925 OOP_SetAttrs(pciDevice
, (struct TagItem
*)&attrs
);
927 RTLD(bug("[%s] CreateUnit: PCI_BaseMem @ 0x%p\n", unit
->rtl8139u_name
, unit
->rtl8139u_BaseMem
))
929 unit
->rtl8139u_fe_priv
= AllocMem(sizeof(struct fe_priv
), MEMF_PUBLIC
|MEMF_CLEAR
);
931 rtl8139nic_get_functions(unit
);
933 if (unit
->rtl8139u_fe_priv
)
935 unit
->rtl8139u_fe_priv
->pci_dev
= unit
;
936 InitSemaphore(&unit
->rtl8139u_fe_priv
->lock
);
941 unit
->rtl8139u_irqhandler
.is_Node
.ln_Type
= NT_INTERRUPT
;
942 unit
->rtl8139u_irqhandler
.is_Node
.ln_Pri
= 100;
943 unit
->rtl8139u_irqhandler
.is_Node
.ln_Name
= LIBBASE
->rtl8139b_Device
.dd_Library
.lib_Node
.ln_Name
;
944 unit
->rtl8139u_irqhandler
.is_Code
= (VOID_FUNC
)RTL8139_IntHandlerF
;
945 unit
->rtl8139u_irqhandler
.is_Data
= unit
;
947 unit
->rtl8139u_touthandler
.is_Node
.ln_Type
= NT_INTERRUPT
;
948 unit
->rtl8139u_touthandler
.is_Node
.ln_Pri
= 100;
949 unit
->rtl8139u_touthandler
.is_Node
.ln_Name
= LIBBASE
->rtl8139b_Device
.dd_Library
.lib_Node
.ln_Name
;
950 unit
->rtl8139u_touthandler
.is_Code
= (VOID_FUNC
)RTL8139_TimeoutHandlerF
;
951 unit
->rtl8139u_touthandler
.is_Data
= unit
;
953 unit
->rtl8139u_rx_int
.is_Node
.ln_Type
= NT_INTERRUPT
;
954 unit
->rtl8139u_rx_int
.is_Node
.ln_Name
= unit
->rtl8139u_name
;
955 //unit->rtl8139u_rx_int.is_Code = RTL8139_RX_IntF;
956 unit
->rtl8139u_rx_int
.is_Data
= unit
;
958 unit
->rtl8139u_tx_int
.is_Node
.ln_Type
= NT_INTERRUPT
;
959 unit
->rtl8139u_tx_int
.is_Node
.ln_Name
= unit
->rtl8139u_name
;
960 unit
->rtl8139u_tx_int
.is_Code
= (VOID_FUNC
)RTL8139_TX_IntF
;
961 unit
->rtl8139u_tx_int
.is_Data
= unit
;
963 for (i
=0; i
< REQUEST_QUEUE_COUNT
; i
++)
965 struct MsgPort
*port
= AllocMem(sizeof(struct MsgPort
), MEMF_PUBLIC
| MEMF_CLEAR
);
966 unit
->rtl8139u_request_ports
[i
] = port
;
968 if (port
== NULL
) success
= FALSE
;
972 NEWLIST(&port
->mp_MsgList
);
973 port
->mp_Flags
= PA_IGNORE
;
974 port
->mp_SigTask
= &unit
->rtl8139u_tx_int
;
978 unit
->rtl8139u_request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
982 struct RTL8139Startup
*sm_UD
;
985 if ((sm_UD
= AllocMem(sizeof(struct RTL8139Startup
), MEMF_PUBLIC
| MEMF_CLEAR
)) != NULL
)
987 sprintf((char *)tmpbuff
, RTL8139_TASK_NAME
, unit
->rtl8139u_name
);
989 sm_UD
->rtl8139sm_SyncPort
= CreateMsgPort();
990 sm_UD
->rtl8139sm_Unit
= unit
;
992 unit
->rtl8139u_Process
= CreateNewProcTags(
993 NP_Entry
, (IPTR
)RTL8139_Schedular
,
995 NP_Synchronous
, FALSE
,
997 NP_UserData
, (IPTR
)sm_UD
,
998 NP_StackSize
, 140960,
1001 WaitPort(sm_UD
->rtl8139sm_SyncPort
);
1002 msg
= GetMsg(sm_UD
->rtl8139sm_SyncPort
);
1004 DeleteMsgPort(sm_UD
->rtl8139sm_SyncPort
);
1005 FreeMem(sm_UD
, sizeof(struct RTL8139Startup
));
1007 RTLD(bug("[%s] CreateUnit: Device Initialised. Unit %d @ %p\n", unit
->rtl8139u_name
, unit
->rtl8139u_UnitNum
, unit
))
1013 RTLD(bug("[%s] ERRORS occured during Device setup - ABORTING\n", unit
->rtl8139u_name
))
1020 RTLD(bug("[rtl8139] PANIC! Couldn't get MMIO area. Aborting\n"))
1025 bug("[rtl8139] CreateUnit: Failed to Allocate Unit storage!\n");
1028 DeleteUnit(RTL8139DeviceBase
, unit
);
1033 * DeleteUnit - removes selected unit. Frees all resources and structures.
1035 * The caller should be sure, that given unit is really ready to be freed.
1038 void DeleteUnit(struct RTL8139Base
*RTL8139DeviceBase
, struct RTL8139Unit
*Unit
)
1045 if (Unit
->rtl8139u_Process
)
1047 /* Tell our process to quit, and wait until it does so */
1048 Signal(&Unit
->rtl8139u_Process
->pr_Task
, 1 << Unit
->rtl8139u_signal_0
);
1049 sprintf((char *)tmpbuff
, RTL8139_TASK_NAME
, Unit
->rtl8139u_name
);
1050 while (FindTask(tmpbuff
) != NULL
)
1054 for (i
=0; i
< REQUEST_QUEUE_COUNT
; i
++)
1056 if (Unit
->rtl8139u_request_ports
[i
] != NULL
)
1057 FreeMem(Unit
->rtl8139u_request_ports
[i
], sizeof(struct MsgPort
));
1059 Unit
->rtl8139u_request_ports
[i
] = NULL
;
1062 if (Unit
->rtl8139u_fe_priv
)
1064 FreeMem(Unit
->rtl8139u_fe_priv
, sizeof(struct fe_priv
));
1065 Unit
->rtl8139u_fe_priv
= NULL
;
1068 if (Unit
->rtl8139u_BaseMem
)
1070 HIDD_PCIDriver_UnmapPCI(Unit
->rtl8139u_PCIDriver
,
1071 (APTR
)Unit
->rtl8139u_BaseMem
,
1072 Unit
->rtl8139u_SizeMem
);
1075 FreeMem(Unit
, sizeof(struct RTL8139Unit
));
1079 static struct AddressRange
*FindMulticastRange(LIBBASETYPEPTR LIBBASE
, struct RTL8139Unit
*unit
,
1080 ULONG lower_bound_left
, UWORD lower_bound_right
, ULONG upper_bound_left
, UWORD upper_bound_right
)
1082 struct AddressRange
*range
, *tail
;
1085 range
= (APTR
)unit
->rtl8139u_multicast_ranges
.mlh_Head
;
1086 tail
= (APTR
)&unit
->rtl8139u_multicast_ranges
.mlh_Tail
;
1088 while((range
!= tail
) && !found
)
1090 if((lower_bound_left
== range
->lower_bound_left
) &&
1091 (lower_bound_right
== range
->lower_bound_right
) &&
1092 (upper_bound_left
== range
->upper_bound_left
) &&
1093 (upper_bound_right
== range
->upper_bound_right
))
1096 range
= (APTR
)range
->node
.mln_Succ
;
1105 BOOL
AddMulticastRange(LIBBASETYPEPTR LIBBASE
, struct RTL8139Unit
*unit
, const UBYTE
*lower_bound
,
1106 const UBYTE
*upper_bound
)
1108 struct AddressRange
*range
;
1109 ULONG lower_bound_left
, upper_bound_left
;
1110 UWORD lower_bound_right
, upper_bound_right
;
1112 lower_bound_left
= AROS_BE2LONG(*((ULONG
*)lower_bound
));
1113 lower_bound_right
= AROS_BE2WORD(*((UWORD
*)(lower_bound
+ 4)));
1114 upper_bound_left
= AROS_BE2LONG(*((ULONG
*)upper_bound
));
1115 upper_bound_right
= AROS_BE2WORD(*((UWORD
*)(upper_bound
+ 4)));
1117 range
= FindMulticastRange(LIBBASE
, unit
, lower_bound_left
, lower_bound_right
,
1118 upper_bound_left
, upper_bound_right
);
1124 range
= AllocMem(sizeof(struct AddressRange
), MEMF_PUBLIC
);
1127 range
->lower_bound_left
= lower_bound_left
;
1128 range
->lower_bound_right
= lower_bound_right
;
1129 range
->upper_bound_left
= upper_bound_left
;
1130 range
->upper_bound_right
= upper_bound_right
;
1131 range
->add_count
= 1;
1134 AddTail((APTR
)&unit
->rtl8139u_multicast_ranges
, (APTR
)range
);
1137 if (unit
->rtl8139u_range_count
++ == 0)
1139 unit
->rtl8139u_flags
|= IFF_ALLMULTI
;
1140 unit
->set_multicast(unit
);
1145 return range
!= NULL
;
1148 BOOL
RemMulticastRange(LIBBASETYPEPTR LIBBASE
, struct RTL8139Unit
*unit
, const UBYTE
*lower_bound
, const UBYTE
*upper_bound
)
1150 struct AddressRange
*range
;
1151 ULONG lower_bound_left
, upper_bound_left
;
1152 UWORD lower_bound_right
, upper_bound_right
;
1154 lower_bound_left
= AROS_BE2LONG(*((ULONG
*)lower_bound
));
1155 lower_bound_right
= AROS_BE2WORD(*((UWORD
*)(lower_bound
+ 4)));
1156 upper_bound_left
= AROS_BE2LONG(*((ULONG
*)upper_bound
));
1157 upper_bound_right
= AROS_BE2WORD(*((UWORD
*)(upper_bound
+ 4)));
1159 range
= FindMulticastRange(LIBBASE
, unit
, lower_bound_left
, lower_bound_right
,
1160 upper_bound_left
, upper_bound_right
);
1164 if(--range
->add_count
== 0)
1167 Remove((APTR
)range
);
1169 FreeMem(range
, sizeof(struct AddressRange
));
1171 if (--unit
->rtl8139u_range_count
== 0)
1173 unit
->rtl8139u_flags
&= ~IFF_ALLMULTI
;
1174 unit
->set_multicast(unit
);
1178 return range
!= NULL
;