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>
51 #include LC_LIBDEFS_FILE
54 * Report incoming events to all hyphotetical event receivers
56 VOID
ReportEvents(struct RTL8139Base
*RTL8139DeviceBase
, struct RTL8139Unit
*unit
, ULONG events
)
58 struct IOSana2Req
*request
, *tail
, *next_request
;
61 list
= &unit
->rtl8139u_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 RTL8139Base
*RTL8139DeviceBase
, struct RTL8139Unit
*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 RTL8139Unit
*unit
, UBYTE last_queue
, BYTE error
)
109 struct IORequest
*request
;
111 struct Opener
*opener
, *tail
;
113 RTLD(bug("[%s] unit.FlushUnit\n", unit
->rtl8139u_name
))
115 /* Abort queued operations */
117 for (i
=0; i
<= last_queue
; i
++)
119 while ((request
= (APTR
)GetMsg(unit
->rtl8139u_request_ports
[i
])) != NULL
)
121 request
->io_Error
= IOERR_ABORTED
;
122 ReplyMsg((struct Message
*)request
);
126 opener
= (APTR
)unit
->rtl8139u_Openers
.mlh_Head
;
127 tail
= (APTR
)unit
->rtl8139u_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
;
142 /* Interrupt Rx Support Function ..
143 * It's duty is to iterate throgh RX queue searching for new packets.
145 void RTL8139_RX_Process(struct RTL8139Unit
*unit
)
147 struct RTL8139Base
*RTL8139DeviceBase
= unit
->rtl8139u_device
;
148 struct fe_priv
*np
= unit
->rtl8139u_fe_priv
;
149 UBYTE
*base
= unit
->rtl8139u_BaseMem
;
151 struct TypeStats
*tracker
;
153 struct Opener
*opener
, *opener_tail
;
154 struct IOSana2Req
*request
, *request_tail
;
155 BOOL accepted
, is_orphan
;
157 RTLD(bug("[%s] RTL8139_RX_Process() !!!!\n", unit
->rtl8139u_name
))
159 while((BYTEIN(base
+ RTLr_ChipCmd
) & RxBufEmpty
) == 0)
161 UWORD len
= 0, overspill
= 0;
162 struct eth_frame
*frame
;
164 unsigned short cur_rx
= np
->cur_rx
;
165 unsigned int ring_offset
= cur_rx
% np
->rx_buf_len
;
166 unsigned long rx_status
= *(unsigned long *)(np
->rx_buffer
+ ring_offset
);
167 unsigned int rx_size
= rx_status
>> 16;
169 np
->cur_rx
= (unsigned short)(cur_rx
+ rx_size
+ ETH_CRCSIZE
+ 3) & ~3;
170 WORDOUT(base
+ RTLr_RxBufPtr
, np
->cur_rx
- 16);
172 RTLD(bug("[%s] RTL8139_RX_Process: RecieveBuffers @ 0x%p\n",
173 unit
->rtl8139u_name
, np
->rx_buffer
))
175 RTLD(bug("[%s] RTL8139_RX_Process: Rx = %d [offset=%4.4x, Status=%8.8x Size=%d]\n",
176 unit
->rtl8139u_name
, cur_rx
, ring_offset
, rx_status
, rx_size
))
178 if (rx_status
& (RxBadSymbol
| RxRunt
| RxTooLong
| RxCRCErr
| RxBadAlign
))
180 RTLD(bug("[%s] RTL8139_RX_Process: Ethernet frame had errors, Status %8.8x\n",
181 unit
->rtl8139u_name
, rx_status
))
183 if (rx_status
== 0xffffffff)
185 RTLD(bug("[%s] RTL8139_RX_Process: Invalid Recieve Status\n", unit
->rtl8139u_name
))
189 if (rx_status
& RxTooLong
)
191 RTLD(bug("[%s] RTL8139_RX_Process: Oversized Ethernet Frame\n", unit
->rtl8139u_name
))
194 /* Reset the reciever */
196 BYTEOUT(base
+ RTLr_ChipCmd
, CmdTxEnb
);
198 rtl8139nic_set_rxmode(RTL8139DeviceBase
);
199 BYTEOUT(base
+ RTLr_ChipCmd
, CmdRxEnb
| CmdTxEnb
);
201 else if (rx_status
& RxStatusOK
)
203 len
= rx_size
- ETH_CRCSIZE
;
204 frame
= (UBYTE
*)(np
->rx_buffer
+ ring_offset
+ ETH_CRCSIZE
);
205 RTLD(bug("[%s] RTL8139_RX_Process: frame @ %p, len=%d\n", unit
->rtl8139u_name
, frame
, len
))
207 /* got a valid packet - forward it to the network core */
210 if (ring_offset
+ rx_size
> np
->rx_buf_len
)
212 overspill
= (ring_offset
+ rx_size
) - np
->rx_buf_len
;
213 RTLD(bug("[%s] RTL8139_RX_Process: WRAPPED Frame! (%d bytes overspill)\n", unit
->rtl8139u_name
, overspill
))
214 len
= len
- overspill
;
215 #warning "TODO: We need to copy the wrapped buffer into a temp buff to pass to listeners!"
219 for (j
=0; j
<64; j
++) {
223 bug(" %02x", ((unsigned char*)frame
)[j
]);
227 /* Check for address validity */
228 if(AddressFilter(LIBBASE
, unit
, frame
->eth_packet_dest
))
230 /* Packet is addressed to this driver */
231 packet_type
= AROS_BE2WORD(frame
->eth_packet_type
);
232 RTLD(bug("[%s] RTL8139_RX_Process: Packet IP accepted with type = %d\n", unit
->rtl8139u_name
, packet_type
))
234 opener
= (APTR
)unit
->rtl8139u_Openers
.mlh_Head
;
235 opener_tail
= (APTR
)&unit
->rtl8139u_Openers
.mlh_Tail
;
237 /* Offer packet to every opener */
238 while(opener
!= opener_tail
)
240 request
= (APTR
)opener
->read_port
.mp_MsgList
.lh_Head
;
241 request_tail
= (APTR
)&opener
->read_port
.mp_MsgList
.lh_Tail
;
244 /* Offer packet to each request until it's accepted */
245 while((request
!= request_tail
) && !accepted
)
247 if((request
->ios2_PacketType
== packet_type
)
248 || ((request
->ios2_PacketType
<= ETH_MTU
)
249 && (packet_type
<= ETH_MTU
)))
251 RTLD(bug("[%s] RTL8139_RX_Process: copy packet for opener ..\n", unit
->rtl8139u_name
))
252 CopyPacket(LIBBASE
, unit
, request
, len
, packet_type
, frame
);
255 request
= (struct IOSana2Req
*)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
261 opener
= (APTR
)opener
->node
.mln_Succ
;
264 /* If packet was unwanted, give it to S2_READORPHAN request */
267 unit
->rtl8139u_stats
.UnknownTypesReceived
++;
269 if(!IsMsgPortEmpty(unit
->rtl8139u_request_ports
[ADOPT_QUEUE
]))
271 CopyPacket(LIBBASE
, unit
,
272 (APTR
)unit
->rtl8139u_request_ports
[ADOPT_QUEUE
]->
273 mp_MsgList
.lh_Head
, len
, packet_type
, frame
);
274 RTLD(bug("[%s] RTL8139_RX_Process: packet copied to orphan queue\n", unit
->rtl8139u_name
))
278 /* Update remaining statistics */
279 tracker
= FindTypeStats(LIBBASE
, unit
, &unit
->rtl8139u_type_trackers
, packet_type
);
283 tracker
->stats
.PacketsReceived
++;
284 tracker
->stats
.BytesReceived
+= len
;
287 unit
->rtl8139u_stats
.PacketsReceived
++;
291 RTLD(bug("[%s] RTL8139_RX_Process: Rx Packet Processing complete\n", unit
->rtl8139u_name
))
297 * Interrupt generated by Cause() to push new packets into the NIC interface
299 AROS_UFH3(void, RTL8139_TX_IntF
,
300 AROS_UFHA(struct RTL8139Unit
*, unit
, A1
),
301 AROS_UFHA(APTR
, dummy
, A5
),
302 AROS_UFHA(struct ExecBase
*,SysBase
, A6
))
306 struct fe_priv
*np
= unit
->rtl8139u_fe_priv
;
307 struct RTL8139Base
*RTL8139DeviceBase
= unit
->rtl8139u_device
;
309 BOOL proceed
= FALSE
; /* Fails by default */
311 RTLD(bug("[%s] RTL8139_TX_IntF()\n", unit
->rtl8139u_name
))
313 /* send packet only if there is free space on tx queue. Otherwise do nothing */
314 if (!netif_queue_stopped(unit
))
316 UWORD packet_size
, data_size
;
317 struct IOSana2Req
*request
;
318 struct Opener
*opener
;
322 struct MsgPort
*port
;
323 struct TypeStats
*tracker
;
325 proceed
= TRUE
; /* Success by default */
326 UBYTE
*base
= (UBYTE
*) unit
->rtl8139u_BaseMem
;
327 port
= unit
->rtl8139u_request_ports
[WRITE_QUEUE
];
329 /* Still no error and there are packets to be sent? */
330 while(proceed
&& (!IsMsgPortEmpty(port
)))
332 nr
= np
->tx_current
% NUM_TX_DESC
;
335 request
= (APTR
)port
->mp_MsgList
.lh_Head
;
336 data_size
= packet_size
= request
->ios2_DataLength
;
338 opener
= (APTR
)request
->ios2_BufferManagement
;
340 if (np
->tx_pbuf
[nr
] == NULL
)
342 np
->tx_pbuf
[nr
] = np
->tx_buf
[nr
];
343 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
345 packet_size
+= ETH_PACKET_DATA
;
346 CopyMem(request
->ios2_DstAddr
, &((struct eth_frame
*)np
->tx_buf
[nr
])->eth_packet_dest
, ETH_ADDRESSSIZE
);
347 CopyMem(unit
->rtl8139u_dev_addr
, &((struct eth_frame
*)np
->tx_buf
[nr
])->eth_packet_source
, ETH_ADDRESSSIZE
);
348 ((struct eth_frame
*)np
->tx_buf
[nr
])->eth_packet_type
= AROS_WORD2BE(request
->ios2_PacketType
);
350 buffer
= &((struct eth_frame
*)np
->tx_buf
[nr
])->eth_packet_data
;
353 buffer
= np
->tx_buf
[nr
];
355 if (packet_size
< TX_BUF_SIZE
)
356 memset(buffer
, 0, TX_BUF_SIZE
- packet_size
);
358 if (!opener
->tx_function(buffer
, request
->ios2_Data
, data_size
))
360 error
= S2ERR_NO_RESOURCES
;
361 wire_error
= S2WERR_BUFF_ERROR
;
362 ReportEvents(LIBBASE
, unit
,
363 S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
367 /* Now the packet is already in TX buffer, update flags for NIC */
370 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
)))
373 for (j
=0; j
<64; j
++) {
376 bug(" %02x", ((unsigned char*)np
->tx_buf
[nr
])[j
]);
380 /* Set the ring details for the packet .. */
381 LONGOUT(base
+ RTLr_TxAddr0
+ (nr
<< 2), np
->tx_buf
[nr
]);
382 LONGOUT(base
+ RTLr_TxStatus0
+ (nr
<< 2), np
->tx_flag
| (packet_size
>= ETH_ZLEN
? packet_size
: ETH_ZLEN
));
386 request
->ios2_Req
.io_Error
= error
;
387 request
->ios2_WireError
= wire_error
;
389 Remove((APTR
)request
);
391 ReplyMsg((APTR
)request
);
393 /* Update statistics */
396 tracker
= FindTypeStats(LIBBASE
, unit
, &unit
->rtl8139u_type_trackers
, request
->ios2_PacketType
);
400 tracker
->stats
.PacketsSent
++;
401 tracker
->stats
.BytesSent
+= packet_size
;
410 * If we've just run out of free space on the TX queue, stop
411 * it and give up pushing further frames */
412 if ( (try_count
+ 1) >= NUM_TX_DESC
)
414 RTLD(bug("[%s] output queue full!. Stopping [count = %d, NUM_TX_DESC = %d\n", unit
->rtl8139u_name
, try_count
, NUM_TX_DESC
))
415 netif_stop_queue(unit
);
421 /* Was there success? Enable incomming of new packets */
423 unit
->rtl8139u_request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
425 unit
->rtl8139u_request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_IGNORE
;
431 * Handle timeouts and other strange cases
433 static void RTL8139_TimeoutHandlerF(HIDDT_IRQ_Handler
*irq
, HIDDT_IRQ_HwInfo
*hw
)
435 struct RTL8139Unit
*unit
= (struct RTL8139Unit
*) irq
->h_Data
;
437 struct Device
*TimerBase
= unit
->rtl8139u_TimerSlowReq
->tr_node
.io_Device
;
440 //RTLD(bug("[%s] RTL8139_TimeoutHandlerF()\n", unit->rtl8139u_name))
443 * If timeout timer is expected, and time elapsed - regenerate the
446 if (unit
->rtl8139u_toutNEED
&& (CmpTime(&time
, &unit
->rtl8139u_toutPOLL
) < 0))
448 unit
->rtl8139u_toutNEED
= FALSE
;
449 //Cause(&unit->rtl8139u_tx_end_int);
454 * Interrupt handler called whenever RTL8139 NIC interface generates interrupt.
456 * Please note, that although multicast support could be done on interface
457 * basis, it is done in this function as result of quick integration of both
458 * the forcedeth driver (IFF_ALLMULTI flag) and etherlink3 driver (AddressMatch
461 static void RTL8139_IntHandlerF(HIDDT_IRQ_Handler
*irq
, HIDDT_IRQ_HwInfo
*hw
)
463 struct RTL8139Unit
*unit
= (struct RTL8139Unit
*) irq
->h_Data
;
464 struct fe_priv
*np
= unit
->rtl8139u_fe_priv
;
465 UBYTE
*base
= (UBYTE
*) unit
->rtl8139u_BaseMem
;
466 unsigned int link_changed
, CSCRval
;
467 int interrupt_work
= 20;
469 RTLD(bug("[%s] RTL8139_IntHandlerF()!!!!!!!\n", unit
->rtl8139u_name
))
473 UWORD status
= WORDIN(base
+ RTLr_IntrStatus
);
475 if (status
& RxUnderrun
)
477 CSCRval
= WORDIN(base
+ RTLr_CSCR
);
478 link_changed
= (CSCRval
& CSCR_LinkChangeBit
);
479 RTLD(bug("[%s] RTL8139_IntHandlerF: Link Change : %d\n", unit
->rtl8139u_name
, link_changed
))
480 #warning "TODO: Disable/Enable interface on link change"
481 if (CSCRval
& CSCR_LinkOKBit
) {
482 RTLD(bug("[%s] RTL8139_IntHandlerF: Link Change : Link UP\n", unit
->rtl8139u_name
))
483 BYTEOUT(base
+ RTLr_ChipCmd
, CmdTxEnb
);
484 rtl8139nic_set_rxmode(unit
); // Reset the multicast list
485 BYTEOUT(base
+ RTLr_ChipCmd
, CmdRxEnb
| CmdTxEnb
);
486 unit
->rtl8139u_flags
|= IFF_UP
;
488 RTLD(bug("[%s] RTL8139_IntHandlerF: Link Change : Link DOWN\n", unit
->rtl8139u_name
))
489 unit
->rtl8139u_flags
&= ~IFF_UP
;
493 WORDOUT(base
+ RTLr_IntrStatus
, status
);
495 if ((status
& (RxOK
| RxErr
| RxUnderrun
| RxOverflow
| RxFIFOOver
| TxOK
| TxErr
| PCIErr
| PCSTimeout
)) == 0)
497 RTLD(bug("[%s] RTL8139_IntHandlerF: No work to process..\n", unit
->rtl8139u_name
))
501 if (status
& (RxOK
| RxErr
| RxUnderrun
| RxOverflow
| RxFIFOOver
)) // Chipset has Recieved packet(s)
503 RTLD(bug("[%s] RTL8139_IntHandlerF: Packet Reception Attempt detected!\n", unit
->rtl8139u_name
))
504 RTL8139_RX_Process(unit
);
507 if (status
& (TxOK
| TxErr
)) // Chipset has attempted to Send packet(s)
509 RTLD(bug("[%s] RTL8139_IntHandlerF: Packet Transmition Attempt detected!\n", unit
->rtl8139u_name
))
510 unsigned int dirty_tx
= np
->tx_dirty
;
511 unsigned int tx_cur
= 0;
513 while (tx_cur
< NUM_TX_DESC
)
515 BOOL transmit_error
= FALSE
;
517 if (np
->tx_pbuf
[tx_cur
] != NULL
)
519 ULONG txstatus
= LONGIN(base
+ RTLr_TxStatus0
+ (tx_cur
<< 2));
521 if ((txstatus
& TxStatOK
) | (txstatus
& TxUnderrun
) | (txstatus
& TxAborted
))
523 // N.B: TxCarrierLost is always asserted at 100mbps.
524 if (txstatus
& (TxOutOfWindow
| TxAborted
))
526 RTLD(bug("[%s] RTL8139_IntHandlerF: Packet %d Transmition Error! Tx status %8.8x\n", unit
->rtl8139u_name
, tx_cur
, txstatus
))
527 if (txstatus
& TxAborted
)
529 LONGOUT(base
+ RTLr_TxConfig
, TX_DMA_BURST
<< 8);
531 transmit_error
= TRUE
;
535 if (txstatus
& TxUnderrun
)
537 RTLD(bug("[%s] RTL8139_IntHandlerF: Packet %d Transmition Underrun Error! Adjusting flags\n", unit
->rtl8139u_name
, tx_cur
))
538 if (np
->tx_flag
< 0x00300000)
539 np
->tx_flag
+= 0x00020000;
540 transmit_error
= TRUE
;
544 RTLD(bug("[%s] RTL8139_IntHandlerF: Packet %d Sent Successfully\n", unit
->rtl8139u_name
, tx_cur
))
547 np
->tx_pbuf
[tx_cur
] = NULL
;
553 RTLD(bug("[%s] RTL8139_IntHandlerF: Packet %d still in transmission\n", unit
->rtl8139u_name
, tx_cur
))
558 np
->tx_dirty
= dirty_tx
;
561 if (status
& (PCIErr
| PCSTimeout
)) // Chipset has Reported an ERROR
563 RTLD(bug("[%s] RTL8139_IntHandlerF: ERROR Detected\n", unit
->rtl8139u_name
))
564 if (status
== 0xffff) break; // Missing Chip!
567 if (--interrupt_work
< 0)
569 RTLD(bug("[%s] RTL8139_IntHandlerF: MAX interrupt work reached.\n", unit
->rtl8139u_name
))
570 WORDOUT(base
+ RTLr_IntrStatus
, 0xffff);
578 VOID
CopyPacket(struct RTL8139Base
*RTL8139DeviceBase
, struct RTL8139Unit
*unit
,
579 struct IOSana2Req
*request
, UWORD packet_size
, UWORD packet_type
,
580 struct eth_frame
*buffer
)
582 struct Opener
*opener
;
583 BOOL filtered
= FALSE
;
586 RTLD(bug("[%s] CopyPacket(packet @ %x, len = %d)\n", unit
->rtl8139u_name
, buffer
, packet_size
))
588 /* Set multicast and broadcast flags */
590 request
->ios2_Req
.io_Flags
&= ~(SANA2IOF_BCAST
| SANA2IOF_MCAST
);
591 if((*((ULONG
*)(buffer
->eth_packet_dest
)) == 0xffffffff) &&
592 (*((UWORD
*)(buffer
->eth_packet_dest
+ 4)) == 0xffff))
594 request
->ios2_Req
.io_Flags
|= SANA2IOF_BCAST
;
595 RTLD(bug("[%s] CopyPacket: BROADCAST Flag set\n", unit
->rtl8139u_name
))
597 else if((buffer
->eth_packet_dest
[0] & 0x1) != 0)
599 request
->ios2_Req
.io_Flags
|= SANA2IOF_MCAST
;
600 RTLD(bug("[%s] CopyPacket: MULTICAST Flag set\n", unit
->rtl8139u_name
))
603 /* Set source and destination addresses and packet type */
604 CopyMem(buffer
->eth_packet_source
, request
->ios2_SrcAddr
, ETH_ADDRESSSIZE
);
605 CopyMem(buffer
->eth_packet_dest
, request
->ios2_DstAddr
, ETH_ADDRESSSIZE
);
606 request
->ios2_PacketType
= packet_type
;
608 /* Adjust for cooked packet request */
610 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
612 packet_size
-= ETH_PACKET_DATA
;
613 ptr
= (UBYTE
*)&buffer
->eth_packet_data
[0];
617 ptr
= (UBYTE
*)buffer
;
620 request
->ios2_DataLength
= packet_size
;
622 RTLD(bug("[%s] CopyPacket: packet @ %x (%d bytes)\n", unit
->rtl8139u_name
, ptr
, packet_size
))
626 opener
= request
->ios2_BufferManagement
;
627 if((request
->ios2_Req
.io_Command
== CMD_READ
) &&
628 (opener
->filter_hook
!= NULL
))
629 if(!CallHookPkt(opener
->filter_hook
, request
, ptr
))
631 RTLD(bug("[%s] CopyPacket: packet filtered\n", unit
->rtl8139u_name
))
637 /* Copy packet into opener's buffer and reply packet */
638 RTLD(bug("[%s] CopyPacket: opener recieve packet .. ", unit
->rtl8139u_name
))
639 if(!opener
->rx_function(request
->ios2_Data
, ptr
, packet_size
))
641 RTLD(bug("ERROR occured!!\n"))
642 request
->ios2_Req
.io_Error
= S2ERR_NO_RESOURCES
;
643 request
->ios2_WireError
= S2WERR_BUFF_ERROR
;
644 ReportEvents(LIBBASE
, unit
, S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
| S2EVENT_RX
);
648 RTLD(bug("SUCCESS!!\n"))
651 Remove((APTR
)request
);
653 ReplyMsg((APTR
)request
);
654 RTLD(bug("[%s] CopyPacket: opener notified.\n", unit
->rtl8139u_name
))
658 BOOL
AddressFilter(struct RTL8139Base
*RTL8139DeviceBase
, struct RTL8139Unit
*unit
, UBYTE
*address
)
660 struct AddressRange
*range
, *tail
;
665 /* Check whether address is unicast/broadcast or multicast */
667 address_left
= AROS_BE2LONG(*((ULONG
*)address
));
668 address_right
= AROS_BE2WORD(*((UWORD
*)(address
+ 4)));
670 if((address_left
& 0x01000000) != 0 &&
671 !(address_left
== 0xffffffff && address_right
== 0xffff))
673 /* Check if this multicast address is wanted */
675 range
= (APTR
)unit
->rtl8139u_multicast_ranges
.mlh_Head
;
676 tail
= (APTR
)&unit
->rtl8139u_multicast_ranges
.mlh_Tail
;
679 while((range
!= tail
) && !accept
)
681 if((address_left
> range
->lower_bound_left
||
682 (address_left
== range
->lower_bound_left
&&
683 address_right
>= range
->lower_bound_right
)) &&
684 (address_left
< range
->upper_bound_left
||
685 (address_left
== range
->upper_bound_left
&&
686 address_right
<= range
->upper_bound_right
)))
688 range
= (APTR
)range
->node
.mln_Succ
;
692 unit
->rtl8139u_special_stats
[S2SS_ETHERNET_BADMULTICAST
& 0xffff]++;
700 AROS_UFH3(void, RTL8139_Schedular
,
701 AROS_UFHA(STRPTR
, argPtr
, A0
),
702 AROS_UFHA(ULONG
, argSize
, D0
),
703 AROS_UFHA(struct ExecBase
*, SysBase
, A6
))
707 struct Task
*taskSelf
= FindTask(NULL
);
708 struct RTL8139Startup
*sm_UD
= taskSelf
->tc_UserData
;
709 struct RTL8139Unit
*unit
= sm_UD
->rtl8139sm_Unit
;
711 LIBBASETYPEPTR LIBBASE
= unit
->rtl8139u_device
;
712 struct MsgPort
*reply_port
, *input
;
715 RTLD(bug("[%s] RTL8139_Schedular()\n", taskSelf
->tc_Node
.ln_Name
))
716 RTLD(bug("[%s] RTL8139_Schedular: Setting up device '%s'\n", taskSelf
->tc_Node
.ln_Name
, unit
->rtl8139u_name
))
718 if ((reply_port
= CreateMsgPort()) == NULL
)
720 RTLD(bug("[%s] RTL8139_Schedular: Failed to create Reply message port\n", taskSelf
->tc_Node
.ln_Name
))
723 if ((input
= CreateMsgPort()) == NULL
)
725 RTLD(bug("[%s] RTL8139_Schedular: Failed to create Input message port\n", taskSelf
->tc_Node
.ln_Name
))
728 unit
->rtl8139u_input_port
= input
;
730 /* Randomize the generator with current time */
731 if ((BattClockBase
= OpenResource("battclock.resource")) != NULL
)
733 srandom(ReadBattClock());
736 if ((unit
->rtl8139u_TimerSlowPort
= CreateMsgPort()) != NULL
)
738 unit
->rtl8139u_TimerSlowReq
= (struct timerequest
*)
739 CreateIORequest((struct MsgPort
*)unit
->rtl8139u_TimerSlowPort
, sizeof(struct timerequest
));
741 if (unit
->rtl8139u_TimerSlowReq
)
743 if (!OpenDevice("timer.device", UNIT_VBLANK
,
744 (struct IORequest
*)unit
->rtl8139u_TimerSlowReq
, 0))
746 struct Message
*msg
= AllocVec(sizeof(struct Message
), MEMF_PUBLIC
|MEMF_CLEAR
);
749 RTLD(bug("[%s] RTL8139_Schedular: Got VBLANK unit of timer.device\n", taskSelf
->tc_Node
.ln_Name
))
751 unit
->initialize(unit
);
753 msg
->mn_ReplyPort
= reply_port
;
754 msg
->mn_Length
= sizeof(struct Message
);
756 RTLD(bug("[%s] RTL8139_Schedular: Setup complete. Sending handshake\n", taskSelf
->tc_Node
.ln_Name
))
757 PutMsg(sm_UD
->rtl8139sm_SyncPort
, msg
);
758 WaitPort(reply_port
);
763 RTLD(bug("[%s] RTL8139_Schedular: entering forever loop ... \n", taskSelf
->tc_Node
.ln_Name
))
765 unit
->rtl8139u_signal_0
= AllocSignal(-1);
766 unit
->rtl8139u_signal_1
= AllocSignal(-1);
767 unit
->rtl8139u_signal_2
= AllocSignal(-1);
768 unit
->rtl8139u_signal_3
= AllocSignal(-1);
770 sigset
= 1 << input
->mp_SigBit
|
771 1 << unit
->rtl8139u_signal_0
|
772 1 << unit
->rtl8139u_signal_1
|
773 1 << unit
->rtl8139u_signal_2
|
774 1 << unit
->rtl8139u_signal_3
;
777 ULONG recvd
= Wait(sigset
);
778 if (recvd
& unit
->rtl8139u_signal_0
)
781 * Shutdown process. Driver should close everything
782 * already and waits for our process to complete. Free
783 * memory allocared here and kindly return.
785 unit
->deinitialize(unit
);
786 CloseDevice((struct IORequest
*)unit
->rtl8139u_TimerSlowReq
);
787 DeleteIORequest((struct IORequest
*)unit
->rtl8139u_TimerSlowReq
);
788 DeleteMsgPort(unit
->rtl8139u_TimerSlowPort
);
789 DeleteMsgPort(input
);
790 DeleteMsgPort(reply_port
);
792 RTLD(bug("[%s] RTL8139_Schedular: Process shutdown.\n", taskSelf
->tc_Node
.ln_Name
))
795 else if (recvd
& (1 << input
->mp_SigBit
))
797 struct IOSana2Req
*io
;
799 /* Handle incoming transactions */
800 while ((io
= (struct IOSana2Req
*)GetMsg(input
))!= NULL
);
802 RTLD(bug("[%s] RTL8139_Schedular: Handle incomming transaction.\n", taskSelf
->tc_Node
.ln_Name
))
803 ObtainSemaphore(&unit
->rtl8139u_unit_lock
);
804 handle_request(LIBBASE
, io
);
809 RTLD(bug("[%s] RTL8139_Schedular: Handle incomming signal.\n", taskSelf
->tc_Node
.ln_Name
))
810 /* Handle incoming signals */
821 * Create new RTL8139 ethernet device unit
823 struct RTL8139Unit
*CreateUnit(struct RTL8139Base
*RTL8139DeviceBase
, OOP_Object
*pciDevice
, ULONG CardCapabilities
, char * CardName
, char * CardChipset
)
825 struct RTL8139Unit
*unit
;
829 #if defined(RTL_DEBUG)
832 #warning "TODO: Get option to debug from somewhere .."
833 BOOL doDebug
= FALSE
;
838 bug("[rtl8139] CreateUnit()\n");
841 if ((unit
= AllocMem(sizeof(struct RTL8139Unit
), MEMF_PUBLIC
| MEMF_CLEAR
)) != NULL
)
843 IPTR DeviceID
, base
, len
;
847 unit
->rtl8139u_flags
|= IFF_DEBUG
;
849 unit
->rtl8139u_UnitNum
= RTL8139DeviceBase
->rtl8139b_UnitCount
++;
851 unit
->rtl8139u_Sana2Info
.HardwareType
= S2WireType_Ethernet
;
852 unit
->rtl8139u_Sana2Info
.MTU
= ETH_MTU
;
853 unit
->rtl8139u_Sana2Info
.AddrFieldSize
= 8 * ETH_ADDRESSSIZE
;
855 if ((unit
->rtl8139u_name
= AllocVec(8 + (unit
->rtl8139u_UnitNum
/10) + 2, MEMF_CLEAR
|MEMF_PUBLIC
)) == NULL
)
857 FreeMem(unit
, sizeof(struct RTL8139Unit
));
860 sprintf((char *)unit
->rtl8139u_name
, "rtl8139.%d", unit
->rtl8139u_UnitNum
);
862 RTLD(bug("[rtl8139] CreateUnit: Unit allocated @ 0x%p\n", unit
))
864 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_ProductID
, &DeviceID
);
865 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Driver
, (APTR
)&driver
);
867 unit
->rtl8139u_rtl_cardname
= CardName
;
868 unit
->rtl8139u_rtl_chipname
= CardChipset
;
869 unit
->rtl8139u_rtl_chipcapabilities
= CardCapabilities
;
871 unit
->rtl8139u_device
= RTL8139DeviceBase
;
872 unit
->rtl8139u_DeviceID
= DeviceID
;
873 unit
->rtl8139u_PCIDevice
= pciDevice
;
874 unit
->rtl8139u_PCIDriver
= driver
;
876 unit
->rtl8139u_mtu
= unit
->rtl8139u_Sana2Info
.MTU
;
878 InitSemaphore(&unit
->rtl8139u_unit_lock
);
879 NEWLIST(&unit
->rtl8139u_Openers
);
880 NEWLIST(&unit
->rtl8139u_multicast_ranges
);
881 NEWLIST(&unit
->rtl8139u_type_trackers
);
883 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_INTLine
, &unit
->rtl8139u_IRQ
);
884 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Base1
, &unit
->rtl8139u_BaseIO
);
885 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Base0
, &base
);
886 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Size0
, &len
);
888 RTLD(bug("[%s] CreateUnit: INT:%d, base1:0x%p, base0:0x%p, size0:%d\n", unit
->rtl8139u_name
,
889 unit
->rtl8139u_IRQ
, unit
->rtl8139u_BaseIO
,
892 unit
->rtl8139u_BaseMem
= (IPTR
)HIDD_PCIDriver_MapPCI(driver
, (APTR
)base
, len
);
893 unit
->rtl8139u_SizeMem
= len
;
895 if (unit
->rtl8139u_BaseMem
)
897 struct TagItem attrs
[] = {
898 { aHidd_PCIDevice_isIO
, TRUE
},
899 { aHidd_PCIDevice_isMEM
, TRUE
},
900 { aHidd_PCIDevice_isMaster
, TRUE
},
903 OOP_SetAttrs(pciDevice
, (struct TagItem
*)&attrs
);
905 RTLD(bug("[%s] CreateUnit: PCI_BaseMem @ 0x%p\n", unit
->rtl8139u_name
, unit
->rtl8139u_BaseMem
))
907 unit
->rtl8139u_fe_priv
= AllocMem(sizeof(struct fe_priv
), MEMF_PUBLIC
|MEMF_CLEAR
);
909 rtl8139nic_get_functions(unit
);
911 if (unit
->rtl8139u_fe_priv
)
913 unit
->rtl8139u_fe_priv
->pci_dev
= unit
;
914 InitSemaphore(&unit
->rtl8139u_fe_priv
->lock
);
916 unit
->rtl8139u_irqhandler
= AllocMem(sizeof(HIDDT_IRQ_Handler
), MEMF_PUBLIC
|MEMF_CLEAR
);
917 unit
->rtl8139u_touthandler
= AllocMem(sizeof(HIDDT_IRQ_Handler
), MEMF_PUBLIC
|MEMF_CLEAR
);
919 if (unit
->rtl8139u_irqhandler
&& unit
->rtl8139u_touthandler
)
923 unit
->rtl8139u_irqhandler
->h_Node
.ln_Pri
= 100;
924 unit
->rtl8139u_irqhandler
->h_Node
.ln_Name
= LIBBASE
->rtl8139b_Device
.dd_Library
.lib_Node
.ln_Name
;
925 unit
->rtl8139u_irqhandler
->h_Code
= RTL8139_IntHandlerF
;
926 unit
->rtl8139u_irqhandler
->h_Data
= unit
;
928 unit
->rtl8139u_touthandler
->h_Node
.ln_Pri
= 100;
929 unit
->rtl8139u_touthandler
->h_Node
.ln_Name
= LIBBASE
->rtl8139b_Device
.dd_Library
.lib_Node
.ln_Name
;
930 unit
->rtl8139u_touthandler
->h_Code
= RTL8139_TimeoutHandlerF
;
931 unit
->rtl8139u_touthandler
->h_Data
= unit
;
933 unit
->rtl8139u_rx_int
.is_Node
.ln_Name
= unit
->rtl8139u_name
;
934 //unit->rtl8139u_rx_int.is_Code = RTL8139_RX_IntF;
935 unit
->rtl8139u_rx_int
.is_Data
= unit
;
937 unit
->rtl8139u_tx_int
.is_Node
.ln_Name
= unit
->rtl8139u_name
;
938 unit
->rtl8139u_tx_int
.is_Code
= RTL8139_TX_IntF
;
939 unit
->rtl8139u_tx_int
.is_Data
= unit
;
941 for (i
=0; i
< REQUEST_QUEUE_COUNT
; i
++)
943 struct MsgPort
*port
= AllocMem(sizeof(struct MsgPort
), MEMF_PUBLIC
| MEMF_CLEAR
);
944 unit
->rtl8139u_request_ports
[i
] = port
;
946 if (port
== NULL
) success
= FALSE
;
950 NEWLIST(&port
->mp_MsgList
);
951 port
->mp_Flags
= PA_IGNORE
;
952 port
->mp_SigTask
= &unit
->rtl8139u_tx_int
;
956 unit
->rtl8139u_request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
960 struct RTL8139Startup
*sm_UD
;
963 if ((sm_UD
= AllocMem(sizeof(struct RTL8139Startup
), MEMF_PUBLIC
| MEMF_CLEAR
)) != NULL
)
965 sprintf((char *)tmpbuff
, RTL8139_TASK_NAME
, unit
->rtl8139u_name
);
967 sm_UD
->rtl8139sm_SyncPort
= CreateMsgPort();
968 sm_UD
->rtl8139sm_Unit
= unit
;
970 unit
->rtl8139u_Process
= CreateNewProcTags(
971 NP_Entry
, (IPTR
)RTL8139_Schedular
,
973 NP_Synchronous
, FALSE
,
975 NP_UserData
, (IPTR
)sm_UD
,
976 NP_StackSize
, 140960,
979 WaitPort(sm_UD
->rtl8139sm_SyncPort
);
980 msg
= GetMsg(sm_UD
->rtl8139sm_SyncPort
);
982 DeleteMsgPort(sm_UD
->rtl8139sm_SyncPort
);
983 FreeMem(sm_UD
, sizeof(struct RTL8139Startup
));
985 RTLD(bug("[%s] CreateUnit: Device Initialised. Unit %d @ %p\n", unit
->rtl8139u_name
, unit
->rtl8139u_UnitNum
, unit
))
991 RTLD(bug("[%s] ERRORS occured during Device setup - ABORTING\n", unit
->rtl8139u_name
))
998 RTLD(bug("[rtl8139] PANIC! Couldn't get MMIO area. Aborting\n"))
1003 bug("[rtl8139] CreateUnit: Failed to Allocate Unit storage!\n");
1006 DeleteUnit(RTL8139DeviceBase
, unit
);
1011 * DeleteUnit - removes selected unit. Frees all resources and structures.
1013 * The caller should be sure, that given unit is really ready to be freed.
1016 void DeleteUnit(struct RTL8139Base
*RTL8139DeviceBase
, struct RTL8139Unit
*Unit
)
1021 if (Unit
->rtl8139u_Process
)
1023 Signal(&Unit
->rtl8139u_Process
->pr_Task
, Unit
->rtl8139u_signal_0
);
1026 for (i
=0; i
< REQUEST_QUEUE_COUNT
; i
++)
1028 if (Unit
->rtl8139u_request_ports
[i
] != NULL
)
1029 FreeMem(Unit
->rtl8139u_request_ports
[i
], sizeof(struct MsgPort
));
1031 Unit
->rtl8139u_request_ports
[i
] = NULL
;
1034 if (Unit
->rtl8139u_irqhandler
)
1036 FreeMem(Unit
->rtl8139u_irqhandler
, sizeof(HIDDT_IRQ_Handler
));
1039 if (Unit
->rtl8139u_fe_priv
)
1041 FreeMem(Unit
->rtl8139u_fe_priv
, sizeof(struct fe_priv
));
1042 Unit
->rtl8139u_fe_priv
= NULL
;
1045 if (Unit
->rtl8139u_BaseMem
)
1047 HIDD_PCIDriver_UnmapPCI(Unit
->rtl8139u_PCIDriver
,
1048 (APTR
)Unit
->rtl8139u_BaseMem
,
1049 Unit
->rtl8139u_SizeMem
);
1052 FreeMem(Unit
, sizeof(struct RTL8139Unit
));
1056 static struct AddressRange
*FindMulticastRange(LIBBASETYPEPTR LIBBASE
, struct RTL8139Unit
*unit
,
1057 ULONG lower_bound_left
, UWORD lower_bound_right
, ULONG upper_bound_left
, UWORD upper_bound_right
)
1059 struct AddressRange
*range
, *tail
;
1062 range
= (APTR
)unit
->rtl8139u_multicast_ranges
.mlh_Head
;
1063 tail
= (APTR
)&unit
->rtl8139u_multicast_ranges
.mlh_Tail
;
1065 while((range
!= tail
) && !found
)
1067 if((lower_bound_left
== range
->lower_bound_left
) &&
1068 (lower_bound_right
== range
->lower_bound_right
) &&
1069 (upper_bound_left
== range
->upper_bound_left
) &&
1070 (upper_bound_right
== range
->upper_bound_right
))
1073 range
= (APTR
)range
->node
.mln_Succ
;
1082 BOOL
AddMulticastRange(LIBBASETYPEPTR LIBBASE
, struct RTL8139Unit
*unit
, const UBYTE
*lower_bound
,
1083 const UBYTE
*upper_bound
)
1085 struct AddressRange
*range
;
1086 ULONG lower_bound_left
, upper_bound_left
;
1087 UWORD lower_bound_right
, upper_bound_right
;
1089 lower_bound_left
= AROS_BE2LONG(*((ULONG
*)lower_bound
));
1090 lower_bound_right
= AROS_BE2WORD(*((UWORD
*)(lower_bound
+ 4)));
1091 upper_bound_left
= AROS_BE2LONG(*((ULONG
*)upper_bound
));
1092 upper_bound_right
= AROS_BE2WORD(*((UWORD
*)(upper_bound
+ 4)));
1094 range
= FindMulticastRange(LIBBASE
, unit
, lower_bound_left
, lower_bound_right
,
1095 upper_bound_left
, upper_bound_right
);
1101 range
= AllocMem(sizeof(struct AddressRange
), MEMF_PUBLIC
);
1104 range
->lower_bound_left
= lower_bound_left
;
1105 range
->lower_bound_right
= lower_bound_right
;
1106 range
->upper_bound_left
= upper_bound_left
;
1107 range
->upper_bound_right
= upper_bound_right
;
1108 range
->add_count
= 1;
1111 AddTail((APTR
)&unit
->rtl8139u_multicast_ranges
, (APTR
)range
);
1114 if (unit
->rtl8139u_range_count
++ == 0)
1116 unit
->rtl8139u_flags
|= IFF_ALLMULTI
;
1117 unit
->set_multicast(unit
);
1122 return range
!= NULL
;
1125 BOOL
RemMulticastRange(LIBBASETYPEPTR LIBBASE
, struct RTL8139Unit
*unit
, const UBYTE
*lower_bound
, const UBYTE
*upper_bound
)
1127 struct AddressRange
*range
;
1128 ULONG lower_bound_left
, upper_bound_left
;
1129 UWORD lower_bound_right
, upper_bound_right
;
1131 lower_bound_left
= AROS_BE2LONG(*((ULONG
*)lower_bound
));
1132 lower_bound_right
= AROS_BE2WORD(*((UWORD
*)(lower_bound
+ 4)));
1133 upper_bound_left
= AROS_BE2LONG(*((ULONG
*)upper_bound
));
1134 upper_bound_right
= AROS_BE2WORD(*((UWORD
*)(upper_bound
+ 4)));
1136 range
= FindMulticastRange(LIBBASE
, unit
, lower_bound_left
, lower_bound_right
,
1137 upper_bound_left
, upper_bound_right
);
1141 if(--range
->add_count
== 0)
1144 Remove((APTR
)range
);
1146 FreeMem(range
, sizeof(struct AddressRange
));
1148 if (--unit
->rtl8139u_range_count
== 0)
1150 unit
->rtl8139u_flags
&= ~IFF_ALLMULTI
;
1151 unit
->set_multicast(unit
);
1155 return range
!= NULL
;