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>
48 #include "via-rhine.h"
50 #include LC_LIBDEFS_FILE
53 * Report incoming events to all hyphotetical event receivers
55 VOID
ReportEvents(struct VIARHINEBase
*VIARHINEDeviceBase
, struct VIARHINEUnit
*unit
, ULONG events
)
57 struct IOSana2Req
*request
, *tail
, *next_request
;
60 list
= &unit
->rhineu_request_ports
[EVENT_QUEUE
]->mp_MsgList
;
61 next_request
= (APTR
)list
->lh_Head
;
62 tail
= (APTR
)&list
->lh_Tail
;
64 /* Go through list of event listeners. If send messages to receivers if event found */
66 while(next_request
!= tail
)
68 request
= next_request
;
69 next_request
= (APTR
)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
71 if((request
->ios2_WireError
&events
) != 0)
73 request
->ios2_WireError
= events
;
74 Remove((APTR
)request
);
75 ReplyMsg((APTR
)request
);
83 struct TypeStats
*FindTypeStats(struct VIARHINEBase
*VIARHINEDeviceBase
, struct VIARHINEUnit
*unit
,
84 struct MinList
*list
, ULONG packet_type
)
86 struct TypeStats
*stats
, *tail
;
89 stats
= (APTR
)list
->mlh_Head
;
90 tail
= (APTR
)&list
->mlh_Tail
;
92 while(stats
!= tail
&& !found
)
94 if(stats
->packet_type
== packet_type
)
97 stats
= (APTR
)stats
->node
.mln_Succ
;
106 void FlushUnit(LIBBASETYPEPTR LIBBASE
, struct VIARHINEUnit
*unit
, UBYTE last_queue
, BYTE error
)
108 struct IORequest
*request
;
110 struct Opener
*opener
, *tail
;
112 D(bug("%s unit.FlushUnit\n", unit
->rhineu_name
));
114 /* Abort queued operations */
116 for (i
=0; i
<= last_queue
; i
++)
118 while ((request
= (APTR
)GetMsg(unit
->rhineu_request_ports
[i
])) != NULL
)
120 request
->io_Error
= IOERR_ABORTED
;
121 ReplyMsg((struct Message
*)request
);
125 opener
= (APTR
)unit
->rhineu_Openers
.mlh_Head
;
126 tail
= (APTR
)&unit
->rhineu_Openers
.mlh_Tail
;
128 /* Flush every opener's read queue */
130 while(opener
!= tail
)
132 while ((request
= (APTR
)GetMsg(&opener
->read_port
)) != NULL
)
134 request
->io_Error
= error
;
135 ReplyMsg((struct Message
*)request
);
137 opener
= (struct Opener
*)opener
->node
.mln_Succ
;
142 * Interrupt handler called whenever RTL8139 NIC interface generates interrupt.
143 * It's duty is to iterate throgh RX queue searching for new packets.
145 * Please note, that allthough multicast support could be done on interface
146 * basis, it is done in this function as result of quick integration of both
147 * the forcedeth driver (IFF_ALLMULTI flag) and etherling3 driver (AddressMatch
150 AROS_INTH1(VIARHINE_RX_IntF
, struct VIARHINEUnit
*, unit
)
154 struct VIARHINEBase
*VIARHINEDeviceBase
= unit
->rhineu_device
;
155 struct fe_priv
*np
= unit
->rhineu_fe_priv
;
157 struct TypeStats
*tracker
;
159 struct Opener
*opener
, *opener_tail
;
160 struct IOSana2Req
*request
, *request_tail
;
161 BOOL accepted
, is_orphan
;
163 UBYTE
*base
= (UBYTE
*) unit
->rhineu_BaseMem
;
167 D(bug("%s: VIARHINE_RX_IntF() !!!!\n", unit
->rhineu_name
));
169 /* Endless loop, with break from inside */
173 struct eth_frame
*frame
;
175 if (count
>= RX_RING_SIZE
)
176 break; /* we scanned the whole ring - do not continue */
178 /* Get the in-queue number */
179 i
= np
->cur_rx
% RX_RING_SIZE
;
181 /* Do we own the packet or the chipset? */
182 if (np
->rx_desc
[i
].rx_status
& DescOwn
)
184 //D(bug("%s: VIARHINE_RX_IntF: buffer %d owned by chipset\n", unit->rhineu_name, i));
185 //goto next_pkt; // still owned by hardware,
189 if (np
->rx_desc
[i
].rx_status
& RxErr
)
191 D(bug("%s: VIARHINE_RX_IntF: buffer %d has recieve error! skipping..\n", unit
->rhineu_name
, i
));
192 goto next_pkt
; // still owned by hardware,
195 if (!(np
->rx_desc
[i
].rx_status
& RxWholePkt
))
197 D(bug("%s: VIARHINE_RX_IntF: buffer %d has recieved oversized packet! skipping..\n", unit
->rhineu_name
, i
));
198 goto next_pkt
; // still owned by hardware,
201 if (np
->rx_desc
[i
].rx_status
& RxOK
)
203 D(bug("%s: VIARHINE_RX_IntF: packet in buffer %d was successfully recieved.\n", unit
->rhineu_name
, i
));
206 D(bug("%s: VIARHINE_RX_IntF: buffer %d @ %x is for us\n", unit
->rhineu_name
, i
, np
->rx_desc
[i
].addr
));
207 /* the packet is for us - get it */
209 /* got a valid packet - forward it to the network core */
210 frame
= (struct eth_frame
*)(IPTR
)np
->rx_desc
[i
].addr
;
213 /* Dump contents of frame if DEBUG enabled */
217 for (j
=0; j
<64; j
++) {
219 D(bug("\n%03x:", j
));
220 D(bug(" %02x", ((unsigned char*)frame
)[j
]));
226 /* Check for address validity */
227 if(AddressFilter(LIBBASE
, unit
, frame
->eth_packet_dest
))
229 /* Packet is addressed to this driver */
230 len
= (np
->rx_desc
[i
].rx_status
>> 16)-4;
232 packet_type
= AROS_BE2WORD(frame
->eth_packet_type
);
233 D(bug("%s: VIARHINE_RX_IntF: Packet IP accepted with type = %d, len = %d, desc_length = %d\n", unit
->rhineu_name
, packet_type
, len
, np
->rx_desc
[i
].desc_length
));
235 opener
= (APTR
)unit
->rhineu_Openers
.mlh_Head
;
236 opener_tail
= (APTR
)&unit
->rhineu_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 D(bug("%s: VIARHINE_RX_IntF: copy packet for opener ..\n", unit
->rhineu_name
));
253 CopyPacket(LIBBASE
, unit
, request
, len
, packet_type
, frame
);
257 (struct IOSana2Req
*)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
262 opener
= (APTR
)opener
->node
.mln_Succ
;
265 /* If packet was unwanted, give it to S2_READORPHAN request */
268 unit
->rhineu_stats
.UnknownTypesReceived
++;
270 if(!IsMsgPortEmpty(unit
->rhineu_request_ports
[ADOPT_QUEUE
]))
272 CopyPacket(LIBBASE
, unit
,
273 (APTR
)unit
->rhineu_request_ports
[ADOPT_QUEUE
]->
274 mp_MsgList
.lh_Head
, len
, packet_type
, frame
);
275 D(bug("%s: VIARHINE_RX_IntF: packet copied to orphan queue\n", unit
->rhineu_name
));
278 np
->rx_desc
[i
].desc_length
= MAX_FRAME_SIZE
; //Set the buffer size back to max (before enabling it)
279 np
->rx_desc
[i
].rx_status
= DescOwn
;
281 WORDOUT(base
, CmdRxDemand
| np
->cmd
);
283 /* Update remaining statistics */
286 FindTypeStats(LIBBASE
, unit
, &unit
->rhineu_type_trackers
, packet_type
);
290 tracker
->stats
.PacketsReceived
++;
291 tracker
->stats
.BytesReceived
+= len
;
295 unit
->rhineu_stats
.PacketsReceived
++;
296 // ((struct rx_ring_desc *)np->ring_addr)[i].BufferStatus = AROS_WORD2LE((1 << 8)|(1 << 9)|(1 << 15)); // Mark packet as available again
309 * Interrupt generated by Cause() to push new packets into the NIC interface
311 AROS_INTH1(VIARHINE_TX_IntF
, struct VIARHINEUnit
*, unit
)
315 struct fe_priv
*np
= unit
->rhineu_fe_priv
;
316 struct VIARHINEBase
*VIARHINEDeviceBase
= unit
->rhineu_device
;
318 BOOL proceed
= FALSE
; /* Fails by default */
320 D(bug("%s: VIARHINE_TX_IntF()\n", unit
->rhineu_name
));
322 /* send packet only if there is free space on tx queue. Otherwise do nothing */
323 if (!netif_queue_stopped(unit
))
325 UWORD packet_size
, data_size
;
326 struct IOSana2Req
*request
;
327 struct Opener
*opener
;
331 struct MsgPort
*port
;
332 struct TypeStats
*tracker
;
334 proceed
= TRUE
; /* Success by default */
335 UBYTE
*base
= (UBYTE
*) unit
->rhineu_BaseMem
;
336 port
= unit
->rhineu_request_ports
[WRITE_QUEUE
];
338 /* Still no error and there are packets to be sent? */
339 while(proceed
&& (!IsMsgPortEmpty(port
)))
342 if (try_count
>= (TX_BUFFERS
* 3))
344 /* TODO: We should probably report that we couldnt send the packet here.. */
345 D(bug("%s: VIARHINE_TX_IntF: Send FAILED! no free Tx buffer(s)\n", unit
->rhineu_name
));
349 nr
= np
->tx_current
% TX_BUFFERS
;
352 if (np
->tx_desc
[nr
].tx_status
& DescOwn
)
354 D(bug("%s: VIARHINE_TX_IntF: Buffer %d in use!\n", unit
->rhineu_name
, nr
));
359 request
= (APTR
)port
->mp_MsgList
.lh_Head
;
360 data_size
= packet_size
= request
->ios2_DataLength
;
362 opener
= (APTR
)request
->ios2_BufferManagement
;
364 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
366 packet_size
+= ETH_PACKET_DATA
;
367 CopyMem(request
->ios2_DstAddr
, &((struct eth_frame
*)(IPTR
)np
->tx_desc
[nr
].addr
)->eth_packet_dest
, ETH_ADDRESSSIZE
);
368 CopyMem(unit
->rhineu_dev_addr
, &((struct eth_frame
*)(IPTR
)np
->tx_desc
[nr
].addr
)->eth_packet_source
, ETH_ADDRESSSIZE
);
369 ((struct eth_frame
*)(IPTR
)np
->tx_desc
[nr
].addr
)->eth_packet_type
= AROS_WORD2BE(request
->ios2_PacketType
);
371 buffer
= (UBYTE
*)&((struct eth_frame
*)(IPTR
)np
->tx_desc
[nr
].addr
)->eth_packet_data
;
374 buffer
= (UBYTE
*)(IPTR
)np
->tx_desc
[nr
].addr
;
376 if (!opener
->tx_function(buffer
, request
->ios2_Data
, data_size
))
378 error
= S2ERR_NO_RESOURCES
;
379 wire_error
= S2WERR_BUFF_ERROR
;
380 ReportEvents(LIBBASE
, unit
,
381 S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
385 /* Now the packet is already in TX buffer, update flags for NIC */
386 D(bug("%s: VIARHINE_TX_IntF: packet %d @ %x [type = %d] queued for transmission.", unit
->rhineu_name
, nr
, np
->tx_desc
[nr
].addr
, ((struct eth_frame
*)(IPTR
)np
->tx_desc
[nr
].addr
)->eth_packet_type
));
388 /* DEBUG? Dump frame if so */
392 for (j
=0; j
<64; j
++) {
394 D(bug("\n%03x:", j
));
395 D(bug(" %02x", ((unsigned char*)(IPTR
)np
->tx_desc
[nr
].addr
)[j
]));
402 /* Set the ring details for the packet .. */
403 np
->tx_desc
[nr
].tx_status
= DescOwn
;
404 np
->tx_desc
[nr
].desc_length
= 0x00e08000 | packet_size
;
405 WORDOUT(base
+ VIAR_ChipCmd
, CmdTxDemand
| np
->cmd
);
406 D(bug("%s: VIARHINE_TX_IntF: Packet Queued.\n", unit
->rhineu_name
));
410 request
->ios2_Req
.io_Error
= error
;
411 request
->ios2_WireError
= wire_error
;
413 Remove((APTR
)request
);
415 ReplyMsg((APTR
)request
);
417 /* Update statistics */
421 tracker
= FindTypeStats(LIBBASE
, unit
, &unit
->rhineu_type_trackers
,
422 request
->ios2_PacketType
);
425 tracker
->stats
.PacketsSent
++;
426 tracker
->stats
.BytesSent
+= packet_size
;
432 /* Was there success? Enable incomming of new packets */
434 unit
->rhineu_request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
436 unit
->rhineu_request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_IGNORE
;
444 * Handle timeouts and other strange cases
446 static AROS_INTH1(VIARHINE_TimeoutHandlerF
, struct VIARHINEUnit
*, dev
)
451 struct Device
*TimerBase
= dev
->rhineu_TimerSlowReq
->tr_node
.io_Device
;
454 //D(bug("%s: VIARHINE_TimeoutHandlerF()\n", dev->rhineu_name));
457 * If timeout timer is expected, and time elapsed - regenerate the
460 if (dev
->rhineu_toutNEED
&& (CmpTime(&time
, &dev
->rhineu_toutPOLL
) < 0))
462 dev
->rhineu_toutNEED
= FALSE
;
463 //Cause(&dev->rhineu_tx_end_int);
472 * The interrupt handler - schedules code execution to proper handlers
474 static AROS_INTH1(VIARHINE_IntHandlerF
, struct VIARHINEUnit
*, dev
)
478 struct VIARHINEBase
*VIARHINEDeviceBase
= dev
->rhineu_device
;
479 struct fe_priv
*np
= dev
->rhineu_fe_priv
;
480 UBYTE
*base
= (UBYTE
*) dev
->rhineu_BaseMem
;
482 // int i, link_changed;
483 int interrupt_work
= 20;
484 // struct Device *TimerBase = dev->rhineu_TimerSlowReq->tr_node.io_Device;
485 // struct timeval time;
487 D(bug("%s: VIARHINE_IntHandlerF()!!!!!!!\n", dev
->rhineu_name
));
491 int status
= WORDIN(base
+ VIAR_IntrStatus
);
492 WORDOUT(base
+ VIAR_IntrStatus
, status
& 0xffff); // Aknowledge All Interrupt SOurces ASAP.
494 if (!(status
& (IntrRxDone
| IntrRxErr
| IntrRxEmpty
| IntrRxOverflow
| IntrRxDropped
| IntrTxDone
| IntrTxAbort
| IntrTxUnderrun
| IntrPCIErr
| IntrStatsMax
| IntrLinkChange
| IntrMIIChange
)))
496 D(bug("%s: VIARHINE_IntHandlerF: No Signals for us!\n", dev
->rhineu_name
));
500 if ( status
& (IntrRxErr
| IntrRxDropped
| IntrRxWakeUp
| IntrRxEmpty
| IntrRxNoBuf
)) // Chipset has Reported a Recieve problem
502 D(bug("%s: VIARHINE_IntHandlerF: Packet Reception Problem detected!\n", dev
->rhineu_name
));
503 WORDOUT(base
, CmdRxDemand
| np
->cmd
);
504 ReportEvents(LIBBASE
, dev
, S2EVENT_ERROR
| S2EVENT_HARDWARE
| S2EVENT_RX
);
505 dev
->rhineu_stats
.BadData
++;
507 else if ( status
& IntrRxDone
) // Chipset has Recieved packet(s)
509 D(bug("%s: VIARHINE_IntHandlerF: Packet Reception Attempt detected!\n", dev
->rhineu_name
));
510 Cause(&dev
->rhineu_rx_int
);
513 if ( status
& IntrTxAbort
) // Chipset has Aborted Packet Transmition
515 D(bug("%s: VIARHINE_IntHandlerF: Chipset has Aborted Packet Transmition!\n", dev
->rhineu_name
));
516 WORDOUT(base
, CmdTxDemand
| np
->cmd
);
517 ReportEvents(LIBBASE
, dev
, S2EVENT_ERROR
| S2EVENT_HARDWARE
| S2EVENT_TX
);
520 if ( status
& IntrTxUnderrun
) // Chipset Reports Tx Underrun
522 D(bug("%s: VIARHINE_IntHandlerF: Chipset Reports Tx Underrun!\n", dev
->rhineu_name
));
523 if (np
->tx_thresh
< 0xe0) BYTEOUT(base
+ VIAR_TxConfig
, np
->tx_thresh
+= 0x20);
524 WORDOUT(base
, CmdTxDemand
| np
->cmd
);
525 ReportEvents(LIBBASE
, dev
, S2EVENT_ERROR
| S2EVENT_HARDWARE
| S2EVENT_TX
);
528 if ( status
& IntrTxDone
) // Chipset has Sent packet(s)
530 D(bug("%s: VIARHINE_IntHandlerF: Packet Transmision detected!\n", dev
->rhineu_name
));
531 dev
->rhineu_stats
.PacketsSent
++;
534 if (--interrupt_work
< 0)
536 D(bug("%s: VIARHINE_IntHandlerF: MAX interrupt work reached.\n", dev
->rhineu_name
));
546 VOID
CopyPacket(struct VIARHINEBase
*VIARHINEDeviceBase
, struct VIARHINEUnit
*unit
,
547 struct IOSana2Req
*request
, UWORD packet_size
, UWORD packet_type
,
548 struct eth_frame
*buffer
)
550 struct Opener
*opener
;
551 BOOL filtered
= FALSE
;
554 D(bug("%s: CopyPacket(packet @ %x, len = %d)\n", unit
->rhineu_name
, buffer
, packet_size
));
556 /* Set multicast and broadcast flags */
558 request
->ios2_Req
.io_Flags
&= ~(SANA2IOF_BCAST
| SANA2IOF_MCAST
);
559 if((*((ULONG
*)(buffer
->eth_packet_dest
)) == 0xffffffff) &&
560 (*((UWORD
*)(buffer
->eth_packet_dest
+ 4)) == 0xffff))
562 request
->ios2_Req
.io_Flags
|= SANA2IOF_BCAST
;
563 D(bug("%s: CopyPacket: BROADCAST Flag set\n", unit
->rhineu_name
));
565 else if((buffer
->eth_packet_dest
[0] & 0x1) != 0)
567 request
->ios2_Req
.io_Flags
|= SANA2IOF_MCAST
;
568 D(bug("%s: CopyPacket: MULTICAST Flag set\n", unit
->rhineu_name
));
571 /* Set source and destination addresses and packet type */
572 CopyMem(buffer
->eth_packet_source
, request
->ios2_SrcAddr
, ETH_ADDRESSSIZE
);
573 CopyMem(buffer
->eth_packet_dest
, request
->ios2_DstAddr
, ETH_ADDRESSSIZE
);
574 request
->ios2_PacketType
= packet_type
;
576 /* Adjust for cooked packet request */
578 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
580 packet_size
-= ETH_PACKET_DATA
;
581 ptr
= (UBYTE
*)&buffer
->eth_packet_data
[0];
585 ptr
= (UBYTE
*)buffer
;
588 request
->ios2_DataLength
= packet_size
;
590 D(bug("%s: CopyPacket: packet @ %x (%d bytes)\n", unit
->rhineu_name
, ptr
, packet_size
));
594 opener
= request
->ios2_BufferManagement
;
595 if((request
->ios2_Req
.io_Command
== CMD_READ
) &&
596 (opener
->filter_hook
!= NULL
))
597 if(!CallHookPkt(opener
->filter_hook
, request
, ptr
))
599 D(bug("%s: CopyPacket: packet filtered\n", unit
->rhineu_name
));
605 /* Copy packet into opener's buffer and reply packet */
606 D(bug("%s: CopyPacket: opener recieve packet .. ", unit
->rhineu_name
));
607 if(!opener
->rx_function(request
->ios2_Data
, ptr
, packet_size
))
609 D(bug("ERROR occured!!\n"));
610 request
->ios2_Req
.io_Error
= S2ERR_NO_RESOURCES
;
611 request
->ios2_WireError
= S2WERR_BUFF_ERROR
;
612 ReportEvents(LIBBASE
, unit
, S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
| S2EVENT_RX
);
616 D(bug("SUCCESS!!\n"));
619 Remove((APTR
)request
);
621 ReplyMsg((APTR
)request
);
622 D(bug("%s: CopyPacket: opener notified.\n", unit
->rhineu_name
));
626 BOOL
AddressFilter(struct VIARHINEBase
*VIARHINEDeviceBase
, struct VIARHINEUnit
*unit
, UBYTE
*address
)
628 struct AddressRange
*range
, *tail
;
633 /* Check whether address is unicast/broadcast or multicast */
635 address_left
= AROS_BE2LONG(*((ULONG
*)address
));
636 address_right
= AROS_BE2WORD(*((UWORD
*)(address
+ 4)));
638 if((address_left
& 0x01000000) != 0 &&
639 !(address_left
== 0xffffffff && address_right
== 0xffff))
641 /* Check if this multicast address is wanted */
643 range
= (APTR
)unit
->rhineu_multicast_ranges
.mlh_Head
;
644 tail
= (APTR
)&unit
->rhineu_multicast_ranges
.mlh_Tail
;
647 while((range
!= tail
) && !accept
)
649 if((address_left
> range
->lower_bound_left
||
650 (address_left
== range
->lower_bound_left
&&
651 address_right
>= range
->lower_bound_right
)) &&
652 (address_left
< range
->upper_bound_left
||
653 (address_left
== range
->upper_bound_left
&&
654 address_right
<= range
->upper_bound_right
)))
656 range
= (APTR
)range
->node
.mln_Succ
;
660 unit
->rhineu_special_stats
[S2SS_ETHERNET_BADMULTICAST
& 0xffff]++;
668 AROS_UFH3(void, VIARHINE_Schedular
,
669 AROS_UFHA(STRPTR
, argPtr
, A0
),
670 AROS_UFHA(ULONG
, argSize
, D0
),
671 AROS_UFHA(struct ExecBase
*, SysBase
, A6
))
675 struct VIARHINEUnit
*dev
= FindTask(NULL
)->tc_UserData
;
676 LIBBASETYPEPTR LIBBASE
= dev
->rhineu_device
;
677 struct MsgPort
*reply_port
, *input
;
679 D(bug("%s VIARHINE_Schedular()\n", dev
->rhineu_name
));
680 D(bug("%s VIARHINE_Schedular: Setting device up\n", dev
->rhineu_name
));
682 reply_port
= CreateMsgPort();
683 input
= CreateMsgPort();
685 dev
->rhineu_input_port
= input
;
687 dev
->rhineu_TimerSlowPort
= CreateMsgPort();
689 if (dev
->rhineu_TimerSlowPort
)
691 dev
->rhineu_TimerSlowReq
= (struct timerequest
*)
692 CreateIORequest((struct MsgPort
*)dev
->rhineu_TimerSlowPort
, sizeof(struct timerequest
));
694 if (dev
->rhineu_TimerSlowReq
)
696 if (!OpenDevice("timer.device", UNIT_VBLANK
,
697 (struct IORequest
*)dev
->rhineu_TimerSlowReq
, 0))
699 struct Message
*msg
= AllocVec(sizeof(struct Message
), MEMF_PUBLIC
|MEMF_CLEAR
);
702 D(bug("%s VIARHINE_Schedular: Got VBLANK unit of timer.device\n", dev
->rhineu_name
));
704 dev
->initialize(dev
);
706 msg
->mn_ReplyPort
= reply_port
;
707 msg
->mn_Length
= sizeof(struct Message
);
709 D(bug("%s VIARHINE_Schedular: Setup complete. Sending handshake\n", dev
->rhineu_name
));
710 PutMsg(LIBBASE
->rhineb_syncport
, msg
);
711 WaitPort(reply_port
);
716 D(bug("%s VIARHINE_Schedular: entering forever loop ... \n", dev
->rhineu_name
));
718 dev
->rhineu_signal_0
= AllocSignal(-1);
719 dev
->rhineu_signal_1
= AllocSignal(-1);
720 dev
->rhineu_signal_2
= AllocSignal(-1);
721 dev
->rhineu_signal_3
= AllocSignal(-1);
723 sigset
= 1 << input
->mp_SigBit
|
724 1 << dev
->rhineu_signal_0
|
725 1 << dev
->rhineu_signal_1
|
726 1 << dev
->rhineu_signal_2
|
727 1 << dev
->rhineu_signal_3
;
730 ULONG recvd
= Wait(sigset
);
731 if (recvd
& dev
->rhineu_signal_0
)
734 * Shutdown process. Driver should close everything
735 * already and waits for our process to complete. Free
736 * memory allocared here and kindly return.
738 dev
->deinitialize(dev
);
739 CloseDevice((struct IORequest
*)dev
->rhineu_TimerSlowReq
);
740 DeleteIORequest((struct IORequest
*)dev
->rhineu_TimerSlowReq
);
741 DeleteMsgPort(dev
->rhineu_TimerSlowPort
);
742 DeleteMsgPort(input
);
743 DeleteMsgPort(reply_port
);
745 D(bug("%s VIARHINE_Schedular: Process shutdown.\n", dev
->rhineu_name
));
748 else if (recvd
& (1 << input
->mp_SigBit
))
750 struct IOSana2Req
*io
;
752 /* Handle incoming transactions */
753 while ((io
= (struct IOSana2Req
*)GetMsg(input
))!= NULL
);
755 D(bug("%s VIARHINE_Schedular: Handle incomming transaction.\n", dev
->rhineu_name
));
756 ObtainSemaphore(&dev
->rhineu_unit_lock
);
757 handle_request(LIBBASE
, io
);
762 D(bug("%s VIARHINE_Schedular: Handle incomming signal.\n", dev
->rhineu_name
));
763 /* Handle incoming signals */
774 * Create new RTL8139 ethernet device unit
776 struct VIARHINEUnit
*CreateUnit(struct VIARHINEBase
*VIARHINEDeviceBase
, OOP_Object
*pciDevice
, ULONG CardCapabilities
, char * CardName
)
781 D(bug("[VIA-RHINE] CreateUnit()\n"));
783 struct VIARHINEUnit
*unit
= AllocMem(sizeof(struct VIARHINEUnit
), MEMF_PUBLIC
| MEMF_CLEAR
);
787 IPTR DeviceID
, base
, len
;
790 D(bug("[VIA-RHINE] CreateUnit: Unit allocated @ %x\n", unit
));
792 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_ProductID
, &DeviceID
);
793 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Driver
, (APTR
)&driver
);
795 unit
->rhineu_cardname
= CardName
;
796 unit
->rhineu_chipcapabilities
= CardCapabilities
;
797 unit
->rhineu_device
= VIARHINEDeviceBase
;
798 unit
->rhineu_DeviceID
= DeviceID
;
799 unit
->rhineu_mtu
= ETH_MTU
;
800 unit
->rhineu_PCIDevice
= pciDevice
;
801 unit
->rhineu_PCIDriver
= driver
;
802 unit
->rhineu_UnitNum
= VIARHINEDeviceBase
->rhineb_UnitCount
++;
804 int unitname_len
= 12 + ((unit
->rhineu_UnitNum
/10)+1);
806 unit
->rhineu_name
= AllocVec(unitname_len
, MEMF_CLEAR
|MEMF_PUBLIC
);
807 D(bug("[VIA-RHINE] CreateUnit: Allocated %d bytes for Unit %d's Name @ %x\n", unitname_len
, unit
->rhineu_UnitNum
, unit
->rhineu_name
));
808 sprintf(unit
->rhineu_name
, "[VIARHINE.%d]", unit
->rhineu_UnitNum
);
810 InitSemaphore(&unit
->rhineu_unit_lock
);
811 NEWLIST(&unit
->rhineu_Openers
);
812 NEWLIST(&unit
->rhineu_multicast_ranges
);
813 NEWLIST(&unit
->rhineu_type_trackers
);
815 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_INTLine
, &unit
->rhineu_IRQ
);
816 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Base1
, &unit
->rhineu_BaseIO
);
817 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Base0
, &base
);
818 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Size0
, &len
);
820 D(bug("%s CreateUnit: INT:%d, base1:%x, base0:%x, size0:%d\n", unit
->rhineu_name
,
821 unit
->rhineu_IRQ
, unit
->rhineu_BaseIO
,
824 unit
->rhineu_BaseMem
= (IPTR
)HIDD_PCIDriver_MapPCI(driver
, (APTR
)base
, len
);
825 unit
->rhineu_SizeMem
= len
;
827 if (unit
->rhineu_BaseMem
)
829 struct TagItem attrs
[] = {
830 { aHidd_PCIDevice_isIO
, TRUE
},
831 { aHidd_PCIDevice_isMEM
, TRUE
},
832 { aHidd_PCIDevice_isMaster
, TRUE
},
835 OOP_SetAttrs(pciDevice
, (struct TagItem
*)&attrs
);
837 D(bug("%s CreateUnit: PCI_BaseMem @ %x\n", unit
->rhineu_name
, unit
->rhineu_BaseMem
));
839 unit
->rhineu_fe_priv
= HIDD_PCIDriver_AllocPCIMem(
840 unit
->rhineu_PCIDriver
,
841 sizeof(struct fe_priv
));
843 viarhinenic_get_functions(unit
);
845 if (unit
->rhineu_fe_priv
)
847 D(bug("%s CreateUnit: NIC Private Data Area @ %x, start @ %x\n", unit
->rhineu_name
, unit
->rhineu_fe_priv
));
849 unit
->rhineu_fe_priv
->pci_dev
= unit
;
850 InitSemaphore(&unit
->rhineu_fe_priv
->lock
);
855 unit
->rhineu_irqhandler
.is_Node
.ln_Type
= NT_INTERRUPT
;
856 unit
->rhineu_irqhandler
.is_Node
.ln_Pri
= 100;
857 unit
->rhineu_irqhandler
.is_Node
.ln_Name
= LIBBASE
->rhineb_Device
.dd_Library
.lib_Node
.ln_Name
;
858 unit
->rhineu_irqhandler
.is_Code
= VIARHINE_IntHandlerF
;
859 unit
->rhineu_irqhandler
.is_Data
= unit
;
861 unit
->rhineu_touthandler
.is_Node
.ln_Type
= NT_INTERRUPT
;
862 unit
->rhineu_touthandler
.is_Node
.ln_Pri
= 100;
863 unit
->rhineu_touthandler
.is_Node
.ln_Name
= LIBBASE
->rhineb_Device
.dd_Library
.lib_Node
.ln_Name
;
864 unit
->rhineu_touthandler
.is_Code
= VIARHINE_TimeoutHandlerF
;
865 unit
->rhineu_touthandler
.is_Data
= unit
;
867 unit
->rhineu_rx_int
.is_Node
.ln_Name
= unit
->rhineu_name
;
868 unit
->rhineu_rx_int
.is_Code
= VIARHINE_RX_IntF
;
869 unit
->rhineu_rx_int
.is_Data
= unit
;
871 unit
->rhineu_tx_int
.is_Node
.ln_Name
= unit
->rhineu_name
;
872 unit
->rhineu_tx_int
.is_Code
= VIARHINE_TX_IntF
;
873 unit
->rhineu_tx_int
.is_Data
= unit
;
875 for (i
=0; i
< REQUEST_QUEUE_COUNT
; i
++)
877 struct MsgPort
*port
= AllocMem(sizeof(struct MsgPort
), MEMF_PUBLIC
| MEMF_CLEAR
);
878 unit
->rhineu_request_ports
[i
] = port
;
880 if (port
== NULL
) success
= FALSE
;
884 NEWLIST(&port
->mp_MsgList
);
885 port
->mp_Flags
= PA_IGNORE
;
886 port
->mp_SigTask
= &unit
->rhineu_tx_int
;
890 unit
->rhineu_request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
894 LIBBASE
->rhineb_syncport
= CreateMsgPort();
896 unit
->rhineu_Process
= CreateNewProcTags(
897 NP_Entry
, (IPTR
)VIARHINE_Schedular
,
898 NP_Name
, VIARHINE_TASK_NAME
,
900 NP_UserData
, (IPTR
)unit
,
901 NP_StackSize
, 140960,
904 WaitPort(LIBBASE
->rhineb_syncport
);
905 msg
= GetMsg(LIBBASE
->rhineb_syncport
);
907 DeleteMsgPort(LIBBASE
->rhineb_syncport
);
909 D(bug("[VIA-RHINE] Unit up and running\n"));
915 D(bug("%s: ERRORS occured during Device setup - ABORTING\n", unit
->rhineu_name
));
921 D(bug("[VIA-RHINE] PANIC! Couldn't get MMIO area. Aborting\n"));
923 DeleteUnit(VIARHINEDeviceBase
, unit
);
928 * DeleteUnit - removes selected unit. Frees all resources and structures.
930 * The caller should be sure, that given unit is really ready to be freed.
933 void DeleteUnit(struct VIARHINEBase
*VIARHINEDeviceBase
, struct VIARHINEUnit
*Unit
)
938 if (Unit
->rhineu_Process
)
940 Signal(&Unit
->rhineu_Process
->pr_Task
, Unit
->rhineu_signal_0
);
943 for (i
=0; i
< REQUEST_QUEUE_COUNT
; i
++)
945 if (Unit
->rhineu_request_ports
[i
] != NULL
)
946 FreeMem(Unit
->rhineu_request_ports
[i
], sizeof(struct MsgPort
));
948 Unit
->rhineu_request_ports
[i
] = NULL
;
951 if (Unit
->rhineu_fe_priv
)
953 FreeMem(Unit
->rhineu_fe_priv
, sizeof(struct fe_priv
));
954 Unit
->rhineu_fe_priv
= NULL
;
957 if (Unit
->rhineu_BaseMem
)
959 HIDD_PCIDriver_UnmapPCI(Unit
->rhineu_PCIDriver
,
960 (APTR
)Unit
->rhineu_BaseMem
,
961 Unit
->rhineu_SizeMem
);
964 FreeMem(Unit
, sizeof(struct VIARHINEUnit
));
968 static struct AddressRange
*FindMulticastRange(LIBBASETYPEPTR LIBBASE
, struct VIARHINEUnit
*unit
,
969 ULONG lower_bound_left
, UWORD lower_bound_right
, ULONG upper_bound_left
, UWORD upper_bound_right
)
971 struct AddressRange
*range
, *tail
;
974 range
= (APTR
)unit
->rhineu_multicast_ranges
.mlh_Head
;
975 tail
= (APTR
)&unit
->rhineu_multicast_ranges
.mlh_Tail
;
977 while((range
!= tail
) && !found
)
979 if((lower_bound_left
== range
->lower_bound_left
) &&
980 (lower_bound_right
== range
->lower_bound_right
) &&
981 (upper_bound_left
== range
->upper_bound_left
) &&
982 (upper_bound_right
== range
->upper_bound_right
))
985 range
= (APTR
)range
->node
.mln_Succ
;
994 BOOL
AddMulticastRange(LIBBASETYPEPTR LIBBASE
, struct VIARHINEUnit
*unit
, const UBYTE
*lower_bound
,
995 const UBYTE
*upper_bound
)
997 struct AddressRange
*range
;
998 ULONG lower_bound_left
, upper_bound_left
;
999 UWORD lower_bound_right
, upper_bound_right
;
1001 lower_bound_left
= AROS_BE2LONG(*((ULONG
*)lower_bound
));
1002 lower_bound_right
= AROS_BE2WORD(*((UWORD
*)(lower_bound
+ 4)));
1003 upper_bound_left
= AROS_BE2LONG(*((ULONG
*)upper_bound
));
1004 upper_bound_right
= AROS_BE2WORD(*((UWORD
*)(upper_bound
+ 4)));
1006 range
= FindMulticastRange(LIBBASE
, unit
, lower_bound_left
, lower_bound_right
,
1007 upper_bound_left
, upper_bound_right
);
1013 range
= AllocMem(sizeof(struct AddressRange
), MEMF_PUBLIC
);
1016 range
->lower_bound_left
= lower_bound_left
;
1017 range
->lower_bound_right
= lower_bound_right
;
1018 range
->upper_bound_left
= upper_bound_left
;
1019 range
->upper_bound_right
= upper_bound_right
;
1020 range
->add_count
= 1;
1023 AddTail((APTR
)&unit
->rhineu_multicast_ranges
, (APTR
)range
);
1026 if (unit
->rhineu_range_count
++ == 0)
1028 unit
->rhineu_flags
|= IFF_ALLMULTI
;
1029 unit
->set_multicast(unit
);
1034 return range
!= NULL
;
1037 BOOL
RemMulticastRange(LIBBASETYPEPTR LIBBASE
, struct VIARHINEUnit
*unit
, const UBYTE
*lower_bound
, const UBYTE
*upper_bound
)
1039 struct AddressRange
*range
;
1040 ULONG lower_bound_left
, upper_bound_left
;
1041 UWORD lower_bound_right
, upper_bound_right
;
1043 lower_bound_left
= AROS_BE2LONG(*((ULONG
*)lower_bound
));
1044 lower_bound_right
= AROS_BE2WORD(*((UWORD
*)(lower_bound
+ 4)));
1045 upper_bound_left
= AROS_BE2LONG(*((ULONG
*)upper_bound
));
1046 upper_bound_right
= AROS_BE2WORD(*((UWORD
*)(upper_bound
+ 4)));
1048 range
= FindMulticastRange(LIBBASE
, unit
, lower_bound_left
, lower_bound_right
,
1049 upper_bound_left
, upper_bound_right
);
1053 if(--range
->add_count
== 0)
1056 Remove((APTR
)range
);
1058 FreeMem(range
, sizeof(struct AddressRange
));
1060 if (--unit
->rhineu_range_count
== 0)
1062 unit
->rhineu_flags
&= ~IFF_ALLMULTI
;
1063 unit
->set_multicast(unit
);
1067 return range
!= NULL
;