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/battclock.h>
42 #include <proto/oop.h>
43 #include <proto/timer.h>
44 #include <proto/utility.h>
49 #include "via-rhine.h"
51 #include LC_LIBDEFS_FILE
54 * Report incoming events to all hyphotetical event receivers
56 VOID
ReportEvents(struct VIARHINEBase
*VIARHINEDeviceBase
, struct VIARHINEUnit
*unit
, ULONG events
)
58 struct IOSana2Req
*request
, *tail
, *next_request
;
61 list
= &unit
->rhineu_request_ports
[EVENT_QUEUE
]->mp_MsgList
;
62 next_request
= (APTR
)list
->lh_Head
;
63 tail
= (APTR
)&list
->lh_Tail
;
65 /* Go through list of event listeners. If send messages to receivers if event found */
67 while(next_request
!= tail
)
69 request
= next_request
;
70 next_request
= (APTR
)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
72 if((request
->ios2_WireError
&events
) != 0)
74 request
->ios2_WireError
= events
;
75 Remove((APTR
)request
);
76 ReplyMsg((APTR
)request
);
84 struct TypeStats
*FindTypeStats(struct VIARHINEBase
*VIARHINEDeviceBase
, struct VIARHINEUnit
*unit
,
85 struct MinList
*list
, ULONG packet_type
)
87 struct TypeStats
*stats
, *tail
;
90 stats
= (APTR
)list
->mlh_Head
;
91 tail
= (APTR
)&list
->mlh_Tail
;
93 while(stats
!= tail
&& !found
)
95 if(stats
->packet_type
== packet_type
)
98 stats
= (APTR
)stats
->node
.mln_Succ
;
107 void FlushUnit(LIBBASETYPEPTR LIBBASE
, struct VIARHINEUnit
*unit
, UBYTE last_queue
, BYTE error
)
109 struct IORequest
*request
;
111 struct Opener
*opener
, *tail
;
113 D(bug("%s unit.FlushUnit\n", unit
->rhineu_name
));
115 /* Abort queued operations */
117 for (i
=0; i
<= last_queue
; i
++)
119 while ((request
= (APTR
)GetMsg(unit
->rhineu_request_ports
[i
])) != NULL
)
121 request
->io_Error
= IOERR_ABORTED
;
122 ReplyMsg((struct Message
*)request
);
126 opener
= (APTR
)unit
->rhineu_Openers
.mlh_Head
;
127 tail
= (APTR
)&unit
->rhineu_Openers
.mlh_Tail
;
129 /* Flush every opener's read queue */
131 while(opener
!= tail
)
133 while ((request
= (APTR
)GetMsg(&opener
->read_port
)) != NULL
)
135 request
->io_Error
= error
;
136 ReplyMsg((struct Message
*)request
);
138 opener
= (struct Opener
*)opener
->node
.mln_Succ
;
143 * Interrupt handler called whenever RTL8139 NIC interface generates interrupt.
144 * It's duty is to iterate throgh RX queue searching for new packets.
146 * Please note, that allthough multicast support could be done on interface
147 * basis, it is done in this function as result of quick integration of both
148 * the forcedeth driver (IFF_ALLMULTI flag) and etherling3 driver (AddressMatch
151 AROS_UFH3(void, VIARHINE_RX_IntF
,
152 AROS_UFHA(struct VIARHINEUnit
*, unit
, A1
),
153 AROS_UFHA(APTR
, dummy
, A5
),
154 AROS_UFHA(struct ExecBase
*,SysBase
, A6
))
158 struct VIARHINEBase
*VIARHINEDeviceBase
= unit
->rhineu_device
;
159 struct fe_priv
*np
= unit
->rhineu_fe_priv
;
161 struct TypeStats
*tracker
;
163 struct Opener
*opener
, *opener_tail
;
164 struct IOSana2Req
*request
, *request_tail
;
165 BOOL accepted
, is_orphan
;
167 UBYTE
*base
= (UBYTE
*) unit
->rhineu_BaseMem
;
171 D(bug("%s: VIARHINE_RX_IntF() !!!!\n", unit
->rhineu_name
));
173 /* Endless loop, with break from inside */
177 struct eth_frame
*frame
;
179 if (count
>= RX_RING_SIZE
)
180 break; /* we scanned the whole ring - do not continue */
182 /* Get the in-queue number */
183 i
= np
->cur_rx
% RX_RING_SIZE
;
185 /* Do we own the packet or the chipset? */
186 if (np
->rx_desc
[i
].rx_status
& DescOwn
)
188 //D(bug("%s: VIARHINE_RX_IntF: buffer %d owned by chipset\n", unit->rhineu_name, i));
189 //goto next_pkt; // still owned by hardware,
193 if (np
->rx_desc
[i
].rx_status
& RxErr
)
195 D(bug("%s: VIARHINE_RX_IntF: buffer %d has recieve error! skipping..\n", unit
->rhineu_name
, i
));
196 goto next_pkt
; // still owned by hardware,
199 if (!(np
->rx_desc
[i
].rx_status
& RxWholePkt
))
201 D(bug("%s: VIARHINE_RX_IntF: buffer %d has recieved oversized packet! skipping..\n", unit
->rhineu_name
, i
));
202 goto next_pkt
; // still owned by hardware,
205 if (np
->rx_desc
[i
].rx_status
& RxOK
)
207 D(bug("%s: VIARHINE_RX_IntF: packet in buffer %d was successfully recieved.\n", unit
->rhineu_name
, i
));
210 D(bug("%s: VIARHINE_RX_IntF: buffer %d @ %x is for us\n", unit
->rhineu_name
, i
, np
->rx_desc
[i
].addr
));
211 /* the packet is for us - get it */
213 /* got a valid packet - forward it to the network core */
214 frame
= (struct eth_frame
*)np
->rx_desc
[i
].addr
;
217 /* Dump contents of frame if DEBUG enabled */
221 for (j
=0; j
<64; j
++) {
223 D(bug("\n%03x:", j
));
224 D(bug(" %02x", ((unsigned char*)frame
)[j
]));
230 /* Check for address validity */
231 if(AddressFilter(LIBBASE
, unit
, frame
->eth_packet_dest
))
233 /* Packet is addressed to this driver */
234 len
= (np
->rx_desc
[i
].rx_status
>> 16)-4;
236 packet_type
= AROS_BE2WORD(frame
->eth_packet_type
);
237 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
));
239 opener
= (APTR
)unit
->rhineu_Openers
.mlh_Head
;
240 opener_tail
= (APTR
)&unit
->rhineu_Openers
.mlh_Tail
;
242 /* Offer packet to every opener */
243 while(opener
!= opener_tail
)
245 request
= (APTR
)opener
->read_port
.mp_MsgList
.lh_Head
;
246 request_tail
= (APTR
)&opener
->read_port
.mp_MsgList
.lh_Tail
;
249 /* Offer packet to each request until it's accepted */
250 while((request
!= request_tail
) && !accepted
)
252 if((request
->ios2_PacketType
== packet_type
)
253 || ((request
->ios2_PacketType
<= ETH_MTU
)
254 && (packet_type
<= ETH_MTU
)))
256 D(bug("%s: VIARHINE_RX_IntF: copy packet for opener ..\n", unit
->rhineu_name
));
257 CopyPacket(LIBBASE
, unit
, request
, len
, packet_type
, frame
);
261 (struct IOSana2Req
*)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
266 opener
= (APTR
)opener
->node
.mln_Succ
;
269 /* If packet was unwanted, give it to S2_READORPHAN request */
272 unit
->rhineu_stats
.UnknownTypesReceived
++;
274 if(!IsMsgPortEmpty(unit
->rhineu_request_ports
[ADOPT_QUEUE
]))
276 CopyPacket(LIBBASE
, unit
,
277 (APTR
)unit
->rhineu_request_ports
[ADOPT_QUEUE
]->
278 mp_MsgList
.lh_Head
, len
, packet_type
, frame
);
279 D(bug("%s: VIARHINE_RX_IntF: packet copied to orphan queue\n", unit
->rhineu_name
));
282 np
->rx_desc
[i
].desc_length
= MAX_FRAME_SIZE
; //Set the buffer size back to max (before enabling it)
283 np
->rx_desc
[i
].rx_status
= DescOwn
;
285 WORDOUT(base
, CmdRxDemand
| np
->cmd
);
287 /* Update remaining statistics */
290 FindTypeStats(LIBBASE
, unit
, &unit
->rhineu_type_trackers
, packet_type
);
294 tracker
->stats
.PacketsReceived
++;
295 tracker
->stats
.BytesReceived
+= len
;
299 unit
->rhineu_stats
.PacketsReceived
++;
300 // ((struct rx_ring_desc *)np->ring_addr)[i].BufferStatus = AROS_WORD2LE((1 << 8)|(1 << 9)|(1 << 15)); // Mark packet as available again
311 * Interrupt generated by Cause() to push new packets into the NIC interface
313 AROS_UFH3(void, VIARHINE_TX_IntF
,
314 AROS_UFHA(struct VIARHINEUnit
*, unit
, A1
),
315 AROS_UFHA(APTR
, dummy
, A5
),
316 AROS_UFHA(struct ExecBase
*,SysBase
, A6
))
320 struct fe_priv
*np
= unit
->rhineu_fe_priv
;
321 struct VIARHINEBase
*VIARHINEDeviceBase
= unit
->rhineu_device
;
323 BOOL proceed
= FALSE
; /* Fails by default */
325 D(bug("%s: VIARHINE_TX_IntF()\n", unit
->rhineu_name
));
327 /* send packet only if there is free space on tx queue. Otherwise do nothing */
328 if (!netif_queue_stopped(unit
))
330 UWORD packet_size
, data_size
;
331 struct IOSana2Req
*request
;
332 struct Opener
*opener
;
336 struct MsgPort
*port
;
337 struct TypeStats
*tracker
;
339 proceed
= TRUE
; /* Success by default */
340 UBYTE
*base
= (UBYTE
*) unit
->rhineu_BaseMem
;
341 port
= unit
->rhineu_request_ports
[WRITE_QUEUE
];
343 /* Still no error and there are packets to be sent? */
344 while(proceed
&& (!IsMsgPortEmpty(port
)))
347 if (try_count
>= (TX_BUFFERS
* 3))
349 #warning "TODO: We should probably report that we couldnt send the packet here.."
350 D(bug("%s: VIARHINE_TX_IntF: Send FAILED! no free Tx buffer(s)\n", unit
->rhineu_name
));
354 nr
= np
->tx_current
% TX_BUFFERS
;
357 if (np
->tx_desc
[nr
].tx_status
& DescOwn
)
359 D(bug("%s: VIARHINE_TX_IntF: Buffer %d in use!\n", unit
->rhineu_name
, nr
));
364 request
= (APTR
)port
->mp_MsgList
.lh_Head
;
365 data_size
= packet_size
= request
->ios2_DataLength
;
367 opener
= (APTR
)request
->ios2_BufferManagement
;
369 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
371 packet_size
+= ETH_PACKET_DATA
;
372 CopyMem(request
->ios2_DstAddr
, &((struct eth_frame
*)np
->tx_desc
[nr
].addr
)->eth_packet_dest
, ETH_ADDRESSSIZE
);
373 CopyMem(unit
->rhineu_dev_addr
, &((struct eth_frame
*)np
->tx_desc
[nr
].addr
)->eth_packet_source
, ETH_ADDRESSSIZE
);
374 ((struct eth_frame
*)np
->tx_desc
[nr
].addr
)->eth_packet_type
= AROS_WORD2BE(request
->ios2_PacketType
);
376 buffer
= (UBYTE
*)&((struct eth_frame
*)np
->tx_desc
[nr
].addr
)->eth_packet_data
;
379 buffer
= (UBYTE
*)np
->tx_desc
[nr
].addr
;
381 if (!opener
->tx_function(buffer
, request
->ios2_Data
, data_size
))
383 error
= S2ERR_NO_RESOURCES
;
384 wire_error
= S2WERR_BUFF_ERROR
;
385 ReportEvents(LIBBASE
, unit
,
386 S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
390 /* Now the packet is already in TX buffer, update flags for NIC */
391 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
*)np
->tx_desc
[nr
].addr
)->eth_packet_type
));
393 /* DEBUG? Dump frame if so */
397 for (j
=0; j
<64; j
++) {
399 D(bug("\n%03x:", j
));
400 D(bug(" %02x", ((unsigned char*)np
->tx_desc
[nr
].addr
)[j
]));
407 /* Set the ring details for the packet .. */
408 np
->tx_desc
[nr
].tx_status
= DescOwn
;
409 np
->tx_desc
[nr
].desc_length
= 0x00e08000 | packet_size
;
410 WORDOUT(base
+ VIAR_ChipCmd
, CmdTxDemand
| np
->cmd
);
411 D(bug("%s: VIARHINE_TX_IntF: Packet Queued.\n", unit
->rhineu_name
));
415 request
->ios2_Req
.io_Error
= error
;
416 request
->ios2_WireError
= wire_error
;
418 Remove((APTR
)request
);
420 ReplyMsg((APTR
)request
);
422 /* Update statistics */
426 tracker
= FindTypeStats(LIBBASE
, unit
, &unit
->rhineu_type_trackers
,
427 request
->ios2_PacketType
);
430 tracker
->stats
.PacketsSent
++;
431 tracker
->stats
.BytesSent
+= packet_size
;
437 /* Was there success? Enable incomming of new packets */
439 unit
->rhineu_request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
441 unit
->rhineu_request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_IGNORE
;
447 * Handle timeouts and other strange cases
449 static void VIARHINE_TimeoutHandlerF(HIDDT_IRQ_Handler
*irq
, HIDDT_IRQ_HwInfo
*hw
)
451 struct VIARHINEUnit
*dev
= (struct VIARHINEUnit
*) irq
->h_Data
;
453 struct Device
*TimerBase
= dev
->rhineu_TimerSlowReq
->tr_node
.io_Device
;
456 //D(bug("%s: VIARHINE_TimeoutHandlerF()\n", dev->rhineu_name));
459 * If timeout timer is expected, and time elapsed - regenerate the
462 if (dev
->rhineu_toutNEED
&& (CmpTime(&time
, &dev
->rhineu_toutPOLL
) < 0))
464 dev
->rhineu_toutNEED
= FALSE
;
465 //Cause(&dev->rhineu_tx_end_int);
470 * The interrupt handler - schedules code execution to proper handlers
472 static void VIARHINE_IntHandlerF(HIDDT_IRQ_Handler
*irq
, HIDDT_IRQ_HwInfo
*hw
)
474 struct VIARHINEUnit
*dev
= (struct VIARHINEUnit
*) irq
->h_Data
;
475 struct VIARHINEBase
*VIARHINEDeviceBase
= dev
->rhineu_device
;
476 struct fe_priv
*np
= dev
->rhineu_fe_priv
;
477 UBYTE
*base
= (UBYTE
*) dev
->rhineu_BaseMem
;
479 int i
, link_changed
, interrupt_work
= 20;
480 struct Device
*TimerBase
= dev
->rhineu_TimerSlowReq
->tr_node
.io_Device
;
483 D(bug("%s: VIARHINE_IntHandlerF()!!!!!!!\n", dev
->rhineu_name
));
487 int status
= WORDIN(base
+ VIAR_IntrStatus
);
488 WORDOUT(base
+ VIAR_IntrStatus
, status
& 0xffff); // Aknowledge All Interrupt SOurces ASAP.
490 if (!(status
& (IntrRxDone
| IntrRxErr
| IntrRxEmpty
| IntrRxOverflow
| IntrRxDropped
| IntrTxDone
| IntrTxAbort
| IntrTxUnderrun
| IntrPCIErr
| IntrStatsMax
| IntrLinkChange
| IntrMIIChange
)))
492 D(bug("%s: VIARHINE_IntHandlerF: No Signals for us!\n", dev
->rhineu_name
));
496 if ( status
& (IntrRxErr
| IntrRxDropped
| IntrRxWakeUp
| IntrRxEmpty
| IntrRxNoBuf
)) // Chipset has Reported a Recieve problem
498 D(bug("%s: VIARHINE_IntHandlerF: Packet Reception Problem detected!\n", dev
->rhineu_name
));
499 WORDOUT(base
, CmdRxDemand
| np
->cmd
);
500 ReportEvents(LIBBASE
, dev
, S2EVENT_ERROR
| S2EVENT_HARDWARE
| S2EVENT_RX
);
501 dev
->rhineu_stats
.BadData
++;
503 else if ( status
& IntrRxDone
) // Chipset has Recieved packet(s)
505 D(bug("%s: VIARHINE_IntHandlerF: Packet Reception Attempt detected!\n", dev
->rhineu_name
));
506 Cause(&dev
->rhineu_rx_int
);
509 if ( status
& IntrTxAbort
) // Chipset has Aborted Packet Transmition
511 D(bug("%s: VIARHINE_IntHandlerF: Chipset has Aborted Packet Transmition!\n", dev
->rhineu_name
));
512 WORDOUT(base
, CmdTxDemand
| np
->cmd
);
513 ReportEvents(LIBBASE
, dev
, S2EVENT_ERROR
| S2EVENT_HARDWARE
| S2EVENT_TX
);
516 if ( status
& IntrTxUnderrun
) // Chipset Reports Tx Underrun
518 D(bug("%s: VIARHINE_IntHandlerF: Chipset Reports Tx Underrun!\n", dev
->rhineu_name
));
519 if (np
->tx_thresh
< 0xe0) BYTEOUT(base
+ VIAR_TxConfig
, np
->tx_thresh
+= 0x20);
520 WORDOUT(base
, CmdTxDemand
| np
->cmd
);
521 ReportEvents(LIBBASE
, dev
, S2EVENT_ERROR
| S2EVENT_HARDWARE
| S2EVENT_TX
);
524 if ( status
& IntrTxDone
) // Chipset has Sent packet(s)
526 D(bug("%s: VIARHINE_IntHandlerF: Packet Transmision detected!\n", dev
->rhineu_name
));
527 dev
->rhineu_stats
.PacketsSent
++;
530 if (--interrupt_work
< 0)
532 D(bug("%s: VIARHINE_IntHandlerF: MAX interrupt work reached.\n", dev
->rhineu_name
));
540 VOID
CopyPacket(struct VIARHINEBase
*VIARHINEDeviceBase
, struct VIARHINEUnit
*unit
,
541 struct IOSana2Req
*request
, UWORD packet_size
, UWORD packet_type
,
542 struct eth_frame
*buffer
)
544 struct Opener
*opener
;
545 BOOL filtered
= FALSE
;
548 D(bug("%s: CopyPacket(packet @ %x, len = %d)\n", unit
->rhineu_name
, buffer
, packet_size
));
550 /* Set multicast and broadcast flags */
552 request
->ios2_Req
.io_Flags
&= ~(SANA2IOF_BCAST
| SANA2IOF_MCAST
);
553 if((*((ULONG
*)(buffer
->eth_packet_dest
)) == 0xffffffff) &&
554 (*((UWORD
*)(buffer
->eth_packet_dest
+ 4)) == 0xffff))
556 request
->ios2_Req
.io_Flags
|= SANA2IOF_BCAST
;
557 D(bug("%s: CopyPacket: BROADCAST Flag set\n", unit
->rhineu_name
));
559 else if((buffer
->eth_packet_dest
[0] & 0x1) != 0)
561 request
->ios2_Req
.io_Flags
|= SANA2IOF_MCAST
;
562 D(bug("%s: CopyPacket: MULTICAST Flag set\n", unit
->rhineu_name
));
565 /* Set source and destination addresses and packet type */
566 CopyMem(buffer
->eth_packet_source
, request
->ios2_SrcAddr
, ETH_ADDRESSSIZE
);
567 CopyMem(buffer
->eth_packet_dest
, request
->ios2_DstAddr
, ETH_ADDRESSSIZE
);
568 request
->ios2_PacketType
= packet_type
;
570 /* Adjust for cooked packet request */
572 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
574 packet_size
-= ETH_PACKET_DATA
;
575 ptr
= (UBYTE
*)&buffer
->eth_packet_data
[0];
579 ptr
= (UBYTE
*)buffer
;
582 request
->ios2_DataLength
= packet_size
;
584 D(bug("%s: CopyPacket: packet @ %x (%d bytes)\n", unit
->rhineu_name
, ptr
, packet_size
));
588 opener
= request
->ios2_BufferManagement
;
589 if((request
->ios2_Req
.io_Command
== CMD_READ
) &&
590 (opener
->filter_hook
!= NULL
))
591 if(!CallHookPkt(opener
->filter_hook
, request
, ptr
))
593 D(bug("%s: CopyPacket: packet filtered\n", unit
->rhineu_name
));
599 /* Copy packet into opener's buffer and reply packet */
600 D(bug("%s: CopyPacket: opener recieve packet .. ", unit
->rhineu_name
));
601 if(!opener
->rx_function(request
->ios2_Data
, ptr
, packet_size
))
603 D(bug("ERROR occured!!\n"));
604 request
->ios2_Req
.io_Error
= S2ERR_NO_RESOURCES
;
605 request
->ios2_WireError
= S2WERR_BUFF_ERROR
;
606 ReportEvents(LIBBASE
, unit
, S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
| S2EVENT_RX
);
610 D(bug("SUCCESS!!\n"));
613 Remove((APTR
)request
);
615 ReplyMsg((APTR
)request
);
616 D(bug("%s: CopyPacket: opener notified.\n", unit
->rhineu_name
));
620 BOOL
AddressFilter(struct VIARHINEBase
*VIARHINEDeviceBase
, struct VIARHINEUnit
*unit
, UBYTE
*address
)
622 struct AddressRange
*range
, *tail
;
627 /* Check whether address is unicast/broadcast or multicast */
629 address_left
= AROS_BE2LONG(*((ULONG
*)address
));
630 address_right
= AROS_BE2WORD(*((UWORD
*)(address
+ 4)));
632 if((address_left
& 0x01000000) != 0 &&
633 !(address_left
== 0xffffffff && address_right
== 0xffff))
635 /* Check if this multicast address is wanted */
637 range
= (APTR
)unit
->rhineu_multicast_ranges
.mlh_Head
;
638 tail
= (APTR
)&unit
->rhineu_multicast_ranges
.mlh_Tail
;
641 while((range
!= tail
) && !accept
)
643 if((address_left
> range
->lower_bound_left
||
644 (address_left
== range
->lower_bound_left
&&
645 address_right
>= range
->lower_bound_right
)) &&
646 (address_left
< range
->upper_bound_left
||
647 (address_left
== range
->upper_bound_left
&&
648 address_right
<= range
->upper_bound_right
)))
650 range
= (APTR
)range
->node
.mln_Succ
;
654 unit
->rhineu_special_stats
[S2SS_ETHERNET_BADMULTICAST
& 0xffff]++;
662 AROS_UFH3(void, VIARHINE_Schedular
,
663 AROS_UFHA(STRPTR
, argPtr
, A0
),
664 AROS_UFHA(ULONG
, argSize
, D0
),
665 AROS_UFHA(struct ExecBase
*, SysBase
, A6
))
669 struct VIARHINEUnit
*dev
= FindTask(NULL
)->tc_UserData
;
670 LIBBASETYPEPTR LIBBASE
= dev
->rhineu_device
;
672 struct MsgPort
*reply_port
, *input
;
674 D(bug("%s VIARHINE_Schedular()\n", dev
->rhineu_name
));
675 D(bug("%s VIARHINE_Schedular: Setting device up\n", dev
->rhineu_name
));
677 reply_port
= CreateMsgPort();
678 input
= CreateMsgPort();
680 dev
->rhineu_input_port
= input
;
682 /* Randomize the generator with current time */
683 BattClockBase
= OpenResource("battclock.resource");
684 srandom(ReadBattClock());
686 dev
->rhineu_TimerSlowPort
= CreateMsgPort();
688 if (dev
->rhineu_TimerSlowPort
)
690 dev
->rhineu_TimerSlowReq
= (struct timerequest
*)
691 CreateIORequest((struct MsgPort
*)dev
->rhineu_TimerSlowPort
, sizeof(struct timerequest
));
693 if (dev
->rhineu_TimerSlowReq
)
695 if (!OpenDevice("timer.device", UNIT_VBLANK
,
696 (struct IORequest
*)dev
->rhineu_TimerSlowReq
, 0))
698 struct Message
*msg
= AllocVec(sizeof(struct Message
), MEMF_PUBLIC
|MEMF_CLEAR
);
701 D(bug("%s VIARHINE_Schedular: Got VBLANK unit of timer.device\n", dev
->rhineu_name
));
703 dev
->initialize(dev
);
705 msg
->mn_ReplyPort
= reply_port
;
706 msg
->mn_Length
= sizeof(struct Message
);
708 D(bug("%s VIARHINE_Schedular: Setup complete. Sending handshake\n", dev
->rhineu_name
));
709 PutMsg(LIBBASE
->rhineb_syncport
, msg
);
710 WaitPort(reply_port
);
715 D(bug("%s VIARHINE_Schedular: entering forever loop ... \n", dev
->rhineu_name
));
717 dev
->rhineu_signal_0
= AllocSignal(-1);
718 dev
->rhineu_signal_1
= AllocSignal(-1);
719 dev
->rhineu_signal_2
= AllocSignal(-1);
720 dev
->rhineu_signal_3
= AllocSignal(-1);
722 sigset
= 1 << input
->mp_SigBit
|
723 1 << dev
->rhineu_signal_0
|
724 1 << dev
->rhineu_signal_1
|
725 1 << dev
->rhineu_signal_2
|
726 1 << dev
->rhineu_signal_3
;
729 ULONG recvd
= Wait(sigset
);
730 if (recvd
& dev
->rhineu_signal_0
)
733 * Shutdown process. Driver should close everything
734 * already and waits for our process to complete. Free
735 * memory allocared here and kindly return.
737 dev
->deinitialize(dev
);
738 CloseDevice((struct IORequest
*)dev
->rhineu_TimerSlowReq
);
739 DeleteIORequest((struct IORequest
*)dev
->rhineu_TimerSlowReq
);
740 DeleteMsgPort(dev
->rhineu_TimerSlowPort
);
741 DeleteMsgPort(input
);
742 DeleteMsgPort(reply_port
);
744 D(bug("%s VIARHINE_Schedular: Process shutdown.\n", dev
->rhineu_name
));
747 else if (recvd
& (1 << input
->mp_SigBit
))
749 struct IOSana2Req
*io
;
751 /* Handle incoming transactions */
752 while ((io
= (struct IOSana2Req
*)GetMsg(input
))!= NULL
);
754 D(bug("%s VIARHINE_Schedular: Handle incomming transaction.\n", dev
->rhineu_name
));
755 ObtainSemaphore(&dev
->rhineu_unit_lock
);
756 handle_request(LIBBASE
, io
);
761 D(bug("%s VIARHINE_Schedular: Handle incomming signal.\n", dev
->rhineu_name
));
762 /* Handle incoming signals */
773 * Create new RTL8139 ethernet device unit
775 struct VIARHINEUnit
*CreateUnit(struct VIARHINEBase
*VIARHINEDeviceBase
, OOP_Object
*pciDevice
, ULONG CardCapabilities
, char * CardName
)
780 D(bug("[VIA-RHINE] CreateUnit()\n"));
782 struct VIARHINEUnit
*unit
= AllocMem(sizeof(struct VIARHINEUnit
), MEMF_PUBLIC
| MEMF_CLEAR
);
786 IPTR DeviceID
, base
, len
;
789 D(bug("[VIA-RHINE] CreateUnit: Unit allocated @ %x\n", unit
));
791 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_ProductID
, &DeviceID
);
792 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Driver
, (APTR
)&driver
);
794 unit
->rhineu_cardname
= CardName
;
795 unit
->rhineu_chipcapabilities
= CardCapabilities
;
796 unit
->rhineu_device
= VIARHINEDeviceBase
;
797 unit
->rhineu_DeviceID
= DeviceID
;
798 unit
->rhineu_mtu
= ETH_MTU
;
799 unit
->rhineu_PCIDevice
= pciDevice
;
800 unit
->rhineu_PCIDriver
= driver
;
801 unit
->rhineu_UnitNum
= VIARHINEDeviceBase
->rhineb_UnitCount
++;
803 int unitname_len
= 12 + ((unit
->rhineu_UnitNum
/10)+1);
805 unit
->rhineu_name
= AllocVec(unitname_len
, MEMF_CLEAR
|MEMF_PUBLIC
);
806 D(bug("[VIA-RHINE] CreateUnit: Allocated %d bytes for Unit %d's Name @ %x\n", unitname_len
, unit
->rhineu_UnitNum
, unit
->rhineu_name
));
807 sprintf(unit
->rhineu_name
, "[VIARHINE.%d]", unit
->rhineu_UnitNum
);
809 InitSemaphore(&unit
->rhineu_unit_lock
);
810 NEWLIST(&unit
->rhineu_Openers
);
811 NEWLIST(&unit
->rhineu_multicast_ranges
);
812 NEWLIST(&unit
->rhineu_type_trackers
);
814 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_INTLine
, &unit
->rhineu_IRQ
);
815 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Base1
, &unit
->rhineu_BaseIO
);
816 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Base0
, &base
);
817 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Size0
, &len
);
819 D(bug("%s CreateUnit: INT:%d, base1:%x, base0:%x, size0:%d\n", unit
->rhineu_name
,
820 unit
->rhineu_IRQ
, unit
->rhineu_BaseIO
,
823 unit
->rhineu_BaseMem
= (IPTR
)HIDD_PCIDriver_MapPCI(driver
, (APTR
)base
, len
);
824 unit
->rhineu_SizeMem
= len
;
826 if (unit
->rhineu_BaseMem
)
828 struct TagItem attrs
[] = {
829 { aHidd_PCIDevice_isIO
, TRUE
},
830 { aHidd_PCIDevice_isMEM
, TRUE
},
831 { aHidd_PCIDevice_isMaster
, TRUE
},
834 OOP_SetAttrs(pciDevice
, (struct TagItem
*)&attrs
);
836 D(bug("%s CreateUnit: PCI_BaseMem @ %x\n", unit
->rhineu_name
, unit
->rhineu_BaseMem
));
838 unit
->rhineu_fe_priv
= HIDD_PCIDriver_AllocPCIMem(
839 unit
->rhineu_PCIDriver
,
840 sizeof(struct fe_priv
));
842 viarhinenic_get_functions(unit
);
844 if (unit
->rhineu_fe_priv
)
846 D(bug("%s CreateUnit: NIC Private Data Area @ %x, start @ %x\n", unit
->rhineu_name
, unit
->rhineu_fe_priv
));
848 unit
->rhineu_fe_priv
->pci_dev
= unit
;
849 InitSemaphore(&unit
->rhineu_fe_priv
->lock
);
851 unit
->rhineu_irqhandler
= AllocMem(sizeof(HIDDT_IRQ_Handler
), MEMF_PUBLIC
|MEMF_CLEAR
);
852 unit
->rhineu_touthandler
= AllocMem(sizeof(HIDDT_IRQ_Handler
), MEMF_PUBLIC
|MEMF_CLEAR
);
854 if (unit
->rhineu_irqhandler
&& unit
->rhineu_touthandler
)
858 unit
->rhineu_irqhandler
->h_Node
.ln_Pri
= 100;
859 unit
->rhineu_irqhandler
->h_Node
.ln_Name
= LIBBASE
->rhineb_Device
.dd_Library
.lib_Node
.ln_Name
;
860 unit
->rhineu_irqhandler
->h_Code
= VIARHINE_IntHandlerF
;
861 unit
->rhineu_irqhandler
->h_Data
= unit
;
863 unit
->rhineu_touthandler
->h_Node
.ln_Pri
= 100;
864 unit
->rhineu_touthandler
->h_Node
.ln_Name
= LIBBASE
->rhineb_Device
.dd_Library
.lib_Node
.ln_Name
;
865 unit
->rhineu_touthandler
->h_Code
= VIARHINE_TimeoutHandlerF
;
866 unit
->rhineu_touthandler
->h_Data
= unit
;
868 unit
->rhineu_rx_int
.is_Node
.ln_Name
= unit
->rhineu_name
;
869 unit
->rhineu_rx_int
.is_Code
= VIARHINE_RX_IntF
;
870 unit
->rhineu_rx_int
.is_Data
= unit
;
872 unit
->rhineu_tx_int
.is_Node
.ln_Name
= unit
->rhineu_name
;
873 unit
->rhineu_tx_int
.is_Code
= VIARHINE_TX_IntF
;
874 unit
->rhineu_tx_int
.is_Data
= unit
;
876 for (i
=0; i
< REQUEST_QUEUE_COUNT
; i
++)
878 struct MsgPort
*port
= AllocMem(sizeof(struct MsgPort
), MEMF_PUBLIC
| MEMF_CLEAR
);
879 unit
->rhineu_request_ports
[i
] = port
;
881 if (port
== NULL
) success
= FALSE
;
885 NEWLIST(&port
->mp_MsgList
);
886 port
->mp_Flags
= PA_IGNORE
;
887 port
->mp_SigTask
= &unit
->rhineu_tx_int
;
891 unit
->rhineu_request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
895 LIBBASE
->rhineb_syncport
= CreateMsgPort();
897 unit
->rhineu_Process
= CreateNewProcTags(
898 NP_Entry
, (IPTR
)VIARHINE_Schedular
,
899 NP_Name
, VIARHINE_TASK_NAME
,
901 NP_UserData
, (IPTR
)unit
,
902 NP_StackSize
, 140960,
905 WaitPort(LIBBASE
->rhineb_syncport
);
906 msg
= GetMsg(LIBBASE
->rhineb_syncport
);
908 DeleteMsgPort(LIBBASE
->rhineb_syncport
);
910 D(bug("[VIA-RHINE] Unit up and running\n"));
916 D(bug("%s: ERRORS occured during Device setup - ABORTING\n", unit
->rhineu_name
));
922 D(bug("[VIA-RHINE] PANIC! Couldn't get MMIO area. Aborting\n"));
924 DeleteUnit(VIARHINEDeviceBase
, unit
);
929 * DeleteUnit - removes selected unit. Frees all resources and structures.
931 * The caller should be sure, that given unit is really ready to be freed.
934 void DeleteUnit(struct VIARHINEBase
*VIARHINEDeviceBase
, struct VIARHINEUnit
*Unit
)
939 if (Unit
->rhineu_Process
)
941 Signal(&Unit
->rhineu_Process
->pr_Task
, Unit
->rhineu_signal_0
);
944 for (i
=0; i
< REQUEST_QUEUE_COUNT
; i
++)
946 if (Unit
->rhineu_request_ports
[i
] != NULL
)
947 FreeMem(Unit
->rhineu_request_ports
[i
], sizeof(struct MsgPort
));
949 Unit
->rhineu_request_ports
[i
] = NULL
;
952 if (Unit
->rhineu_irqhandler
)
954 FreeMem(Unit
->rhineu_irqhandler
, sizeof(HIDDT_IRQ_Handler
));
955 LIBBASE
->rhineb_irq
= NULL
;
958 if (Unit
->rhineu_fe_priv
)
960 FreeMem(Unit
->rhineu_fe_priv
, sizeof(struct fe_priv
));
961 Unit
->rhineu_fe_priv
= NULL
;
964 if (Unit
->rhineu_BaseMem
)
966 HIDD_PCIDriver_UnmapPCI(Unit
->rhineu_PCIDriver
,
967 (APTR
)Unit
->rhineu_BaseMem
,
968 Unit
->rhineu_SizeMem
);
971 FreeMem(Unit
, sizeof(struct VIARHINEUnit
));
975 static struct AddressRange
*FindMulticastRange(LIBBASETYPEPTR LIBBASE
, struct VIARHINEUnit
*unit
,
976 ULONG lower_bound_left
, UWORD lower_bound_right
, ULONG upper_bound_left
, UWORD upper_bound_right
)
978 struct AddressRange
*range
, *tail
;
981 range
= (APTR
)unit
->rhineu_multicast_ranges
.mlh_Head
;
982 tail
= (APTR
)&unit
->rhineu_multicast_ranges
.mlh_Tail
;
984 while((range
!= tail
) && !found
)
986 if((lower_bound_left
== range
->lower_bound_left
) &&
987 (lower_bound_right
== range
->lower_bound_right
) &&
988 (upper_bound_left
== range
->upper_bound_left
) &&
989 (upper_bound_right
== range
->upper_bound_right
))
992 range
= (APTR
)range
->node
.mln_Succ
;
1001 BOOL
AddMulticastRange(LIBBASETYPEPTR LIBBASE
, struct VIARHINEUnit
*unit
, const UBYTE
*lower_bound
,
1002 const UBYTE
*upper_bound
)
1004 struct AddressRange
*range
;
1005 ULONG lower_bound_left
, upper_bound_left
;
1006 UWORD lower_bound_right
, upper_bound_right
;
1008 lower_bound_left
= AROS_BE2LONG(*((ULONG
*)lower_bound
));
1009 lower_bound_right
= AROS_BE2WORD(*((UWORD
*)(lower_bound
+ 4)));
1010 upper_bound_left
= AROS_BE2LONG(*((ULONG
*)upper_bound
));
1011 upper_bound_right
= AROS_BE2WORD(*((UWORD
*)(upper_bound
+ 4)));
1013 range
= FindMulticastRange(LIBBASE
, unit
, lower_bound_left
, lower_bound_right
,
1014 upper_bound_left
, upper_bound_right
);
1020 range
= AllocMem(sizeof(struct AddressRange
), MEMF_PUBLIC
);
1023 range
->lower_bound_left
= lower_bound_left
;
1024 range
->lower_bound_right
= lower_bound_right
;
1025 range
->upper_bound_left
= upper_bound_left
;
1026 range
->upper_bound_right
= upper_bound_right
;
1027 range
->add_count
= 1;
1030 AddTail((APTR
)&unit
->rhineu_multicast_ranges
, (APTR
)range
);
1033 if (unit
->rhineu_range_count
++ == 0)
1035 unit
->rhineu_flags
|= IFF_ALLMULTI
;
1036 unit
->set_multicast(unit
);
1041 return range
!= NULL
;
1044 BOOL
RemMulticastRange(LIBBASETYPEPTR LIBBASE
, struct VIARHINEUnit
*unit
, const UBYTE
*lower_bound
, const UBYTE
*upper_bound
)
1046 struct AddressRange
*range
;
1047 ULONG lower_bound_left
, upper_bound_left
;
1048 UWORD lower_bound_right
, upper_bound_right
;
1050 lower_bound_left
= AROS_BE2LONG(*((ULONG
*)lower_bound
));
1051 lower_bound_right
= AROS_BE2WORD(*((UWORD
*)(lower_bound
+ 4)));
1052 upper_bound_left
= AROS_BE2LONG(*((ULONG
*)upper_bound
));
1053 upper_bound_right
= AROS_BE2WORD(*((UWORD
*)(upper_bound
+ 4)));
1055 range
= FindMulticastRange(LIBBASE
, unit
, lower_bound_left
, lower_bound_right
,
1056 upper_bound_left
, upper_bound_right
);
1060 if(--range
->add_count
== 0)
1063 Remove((APTR
)range
);
1065 FreeMem(range
, sizeof(struct AddressRange
));
1067 if (--unit
->rhineu_range_count
== 0)
1069 unit
->rhineu_flags
&= ~IFF_ALLMULTI
;
1070 unit
->set_multicast(unit
);
1074 return range
!= NULL
;