Fixed a few warnings.
[tangerine.git] / workbench / devs / networks / rtl8168 / unit.c
blob88697cff1ca3595778d9b05fb55c20e046c76055
1 /*
2 * $Id: unit.c 29318 2008-08-29 20:52:01Z NicJA $
3 */
5 /*
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,
19 MA 02111-1307, USA.
22 #include <exec/types.h>
23 #include <exec/resident.h>
24 #include <exec/io.h>
25 #include <exec/ports.h>
26 #include <exec/errors.h>
28 #include <aros/io.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>
46 #include <stdlib.h>
47 #include <stdio.h>
49 #include "rtl8168.h"
50 #include "unit.h"
51 #include LC_LIBDEFS_FILE
54 extern UBYTE MMIO_R8(UBYTE *);
55 extern UWORD MMIO_R16(UWORD *);
56 extern ULONG MMIO_R32(ULONG *);
57 extern void MMIO_W8(UBYTE *, UBYTE);
58 extern void MMIO_W16(UWORD *, UWORD);
59 extern void MMIO_W32(ULONG *, ULONG);
61 extern void rtl8168_CheckLinkStatus(struct net_device *);
64 * Report incoming events to all hyphotetical event receivers
66 VOID ReportEvents(struct RTL8168Base *RTL8168DeviceBase, struct RTL8168Unit *unit, ULONG events)
68 struct IOSana2Req *request, *tail, *next_request;
69 struct List *list;
71 list = &unit->rtl8168u_request_ports[EVENT_QUEUE]->mp_MsgList;
72 next_request = (APTR)list->lh_Head;
73 tail = (APTR)&list->lh_Tail;
75 /* Go through list of event listeners. If send messages to receivers if event found */
76 Disable();
77 while(next_request != tail)
79 request = next_request;
80 next_request = (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
82 if((request->ios2_WireError&events) != 0)
84 request->ios2_WireError = events;
85 Remove((APTR)request);
86 ReplyMsg((APTR)request);
89 Enable();
91 return;
94 struct TypeStats *FindTypeStats(struct RTL8168Base *RTL8168DeviceBase, struct RTL8168Unit *unit,
95 struct MinList *list, ULONG packet_type)
97 struct TypeStats *stats, *tail;
98 BOOL found = FALSE;
100 stats = (APTR)list->mlh_Head;
101 tail = (APTR)&list->mlh_Tail;
103 while(stats != tail && !found)
105 if(stats->packet_type == packet_type)
106 found = TRUE;
107 else
108 stats = (APTR)stats->node.mln_Succ;
111 if(!found)
112 stats = NULL;
114 return stats;
117 void FlushUnit(LIBBASETYPEPTR LIBBASE, struct RTL8168Unit *unit, UBYTE last_queue, BYTE error)
119 struct IORequest *request;
120 UBYTE i;
121 struct Opener *opener, *tail;
123 RTLD(bug("[%s] unit.FlushUnit\n", unit->rtl8168u_name))
125 /* Abort queued operations */
126 for (i=0; i <= last_queue; i++)
128 while ((request = (APTR)GetMsg(unit->rtl8168u_request_ports[i])) != NULL)
130 request->io_Error = IOERR_ABORTED;
131 ReplyMsg((struct Message *)request);
135 opener = (APTR)unit->rtl8168u_Openers.mlh_Head;
136 tail = (APTR)unit->rtl8168u_Openers.mlh_Tail;
138 /* Flush every opener's read queue */
139 while(opener != tail)
141 while ((request = (APTR)GetMsg(&opener->read_port)) != NULL)
143 request->io_Error = error;
144 ReplyMsg((struct Message *)request);
146 opener = (struct Opener *)opener->node.mln_Succ;
150 static inline void rtl8168_MarkToASIC(struct RxDesc *desc, ULONG rx_buf_sz)
152 ULONG eor = AROS_LE2LONG(desc->opts1) & RingEnd;
154 desc->opts1 = AROS_LONG2LE(DescOwn | eor | rx_buf_sz);
157 /* Interrupt Rx Support Function ..
158 * It's duty is to iterate throgh RX queue searching for new packets.
160 void RTL8168_Rx_Process(struct RTL8168Unit *unit)
162 struct RTL8168Base *RTL8168DeviceBase = unit->rtl8168u_device;
163 struct rtl8168_priv *np = unit->rtl8168u_priv;
164 APTR base = unit->rtl8168u_BaseMem;
166 struct TypeStats *tracker;
167 ULONG packet_type;
168 struct Opener *opener, *opener_tail;
169 struct IOSana2Req *request, *request_tail;
170 BOOL accepted, is_orphan;
172 RTLD(bug("[%s] RTL8168_Rx_Process() !!!!\n", unit->rtl8168u_name))
174 struct eth_frame *frame;
176 unsigned short cur_rx, rx_left;
177 cur_rx = np->cur_rx;
178 rx_left = NUM_RX_DESC - np->dirty_rx;
180 RTLD(bug("[%s] RTL8168_Rx_Process: cur_rx = %d, rx_left = %d, dirty = %d\n", unit->rtl8168u_name, cur_rx, rx_left, np->dirty_rx))
182 for (; rx_left > 0; rx_left--, cur_rx++) {
183 unsigned int entry = cur_rx % NUM_RX_DESC;
184 struct RxDesc *desc = np->RxDescArray + entry;
185 ULONG status;
187 status = AROS_LE2LONG(desc->opts1);
189 if (status & DescOwn)
190 break;
192 RTLD(bug("[%s] RTL8168_Rx_Process: Packet %d\n", unit->rtl8168u_name, entry))
194 if (status & RxRES) {
195 RTLD(bug("[%s] RTL8168_Rx_Process: Rx ERROR, status = %08x\n",
196 unit->rtl8168u_name, status))
198 #warning "TODO: record rx errors .."
199 /* RTLDEV->stats.rx_errors++;
201 if (status & (RxRWT | RxRUNT))
202 RTLDEV->stats.rx_length_errors++;
203 if (status & RxCRC)
204 RTLDEV->stats.rx_crc_errors++;
206 rtl8168_MarkToASIC(desc, np->rx_buf_sz);
208 else
210 int pkt_size = (status & 0x00003FFF) - ETH_CRCSIZE;
212 frame = (UBYTE *)(desc->addr);
213 RTLD(bug("[%s] RTL8168_Rx_Process: frame @ %p, pkt_size=%d\n", unit->rtl8168u_name, frame, pkt_size))
215 /* got a valid packet - forward it to the network core */
216 is_orphan = TRUE;
218 RTLDP(
219 int j;
220 for (j = 0; j < pkt_size; j++) {
221 if ((j%16) == 0)
223 if (j != 0)
225 bug("\n");
227 bug("[%s] RTL8168_Rx_Process: %03x:", unit->rtl8168u_name, j);
229 bug(" %02x", ((unsigned char*)frame)[j]);
231 bug("\n")
234 /* Check for address validity */
235 if(AddressFilter(LIBBASE, unit, frame->eth_packet_dest))
237 /* Packet is addressed to this driver */
238 packet_type = AROS_BE2WORD(frame->eth_packet_type);
239 RTLD(bug("[%s] RTL8168_Rx_Process: Packet IP accepted with type = %d\n", unit->rtl8168u_name, packet_type))
241 opener = (APTR)unit->rtl8168u_Openers.mlh_Head;
242 opener_tail = (APTR)&unit->rtl8168u_Openers.mlh_Tail;
244 /* Offer packet to every opener */
245 while(opener != opener_tail)
247 request = (APTR)opener->read_port.mp_MsgList.lh_Head;
248 request_tail = (APTR)&opener->read_port.mp_MsgList.lh_Tail;
249 accepted = FALSE;
251 /* Offer packet to each request until it's accepted */
252 while((request != request_tail) && !accepted)
254 if((request->ios2_PacketType == packet_type)
255 || ((request->ios2_PacketType <= ETH_MTU)
256 && (packet_type <= ETH_MTU)))
258 RTLD(bug("[%s] RTL8168_Rx_Process: copy packet for opener ..\n", unit->rtl8168u_name))
259 CopyPacket(LIBBASE, unit, request, pkt_size, packet_type, frame);
260 accepted = TRUE;
262 request = (struct IOSana2Req *)request->ios2_Req.io_Message.mn_Node.ln_Succ;
265 if(accepted)
266 is_orphan = FALSE;
268 opener = (APTR)opener->node.mln_Succ;
271 /* If packet was unwanted, give it to S2_READORPHAN request */
272 if(is_orphan)
274 unit->rtl8168u_stats.UnknownTypesReceived++;
276 if(!IsMsgPortEmpty(unit->rtl8168u_request_ports[ADOPT_QUEUE]))
278 CopyPacket(LIBBASE, unit,
279 (APTR)unit->rtl8168u_request_ports[ADOPT_QUEUE]->
280 mp_MsgList.lh_Head, pkt_size, packet_type, frame);
281 RTLD(bug("[%s] RTL8168_Rx_Process: packet copied to orphan queue\n", unit->rtl8168u_name))
285 rtl8168_MarkToASIC(desc, (ULONG)np->rx_buf_sz);
287 /* Update remaining statistics */
288 tracker = FindTypeStats(LIBBASE, unit, &unit->rtl8168u_type_trackers, packet_type);
290 if(tracker != NULL)
292 tracker->stats.PacketsReceived++;
293 tracker->stats.BytesReceived += pkt_size;
296 unit->rtl8168u_stats.PacketsReceived++;
299 np->cur_rx = cur_rx;
300 RTLD(bug("[%s] RTL8168_Rx_Process: Rx Packet Processing complete\n", unit->rtl8168u_name))
304 * Interrupt generated by Cause() to push new packets into the NIC interface
306 AROS_UFH3(void, RTL8168_TX_IntF,
307 AROS_UFHA(struct RTL8168Unit *, unit, A1),
308 AROS_UFHA(APTR, dummy, A5),
309 AROS_UFHA(struct ExecBase *,SysBase, A6))
311 AROS_USERFUNC_INIT
313 struct rtl8168_priv *np = unit->rtl8168u_priv;
314 struct RTL8168Base *RTL8168DeviceBase = unit->rtl8168u_device;
315 APTR base = unit->rtl8168u_BaseMem;
317 int nr, try_count=1;
318 BOOL proceed = FALSE; /* Fails by default */
320 RTLD(bug("[%s] RTL8168_TX_IntF()\n", unit->rtl8168u_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;
328 UBYTE *buffer;
329 ULONG wire_error=0;
330 BYTE error;
331 struct MsgPort *port;
333 proceed = TRUE; /* Success by default */
334 port = unit->rtl8168u_request_ports[WRITE_QUEUE];
336 /* Still no error and there are packets to be sent? */
337 while(proceed && (!IsMsgPortEmpty(port)))
339 nr = np->cur_tx % NUM_TX_DESC;
340 error = 0;
342 request = (APTR)port->mp_MsgList.lh_Head;
343 data_size = packet_size = request->ios2_DataLength;
345 opener = (APTR)request->ios2_BufferManagement;
347 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
349 packet_size += ETH_PACKET_DATA;
352 if ((!(AROS_LE2LONG(np->TxDescArray[nr].opts1) & DescOwn)) &&
353 ((np->TxDescArray[nr].addr = AllocMem(packet_size, MEMF_CLEAR | MEMF_PUBLIC)) != NULL))
355 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
357 CopyMem(request->ios2_DstAddr, &((struct eth_frame *)np->TxDescArray[nr].addr)->eth_packet_dest, ETH_ADDRESSSIZE);
358 CopyMem(unit->rtl8168u_dev_addr, &((struct eth_frame *)np->TxDescArray[nr].addr)->eth_packet_source, ETH_ADDRESSSIZE);
359 ((struct eth_frame *)np->TxDescArray[nr].addr)->eth_packet_type = AROS_WORD2BE(request->ios2_PacketType);
361 buffer = &((struct eth_frame *)np->TxDescArray[nr].addr)->eth_packet_data;
363 else
364 buffer = np->TxDescArray[nr].addr;
366 if (!opener->tx_function(buffer, request->ios2_Data, data_size))
368 error = S2ERR_NO_RESOURCES;
369 wire_error = S2WERR_BUFF_ERROR;
370 ReportEvents(LIBBASE, unit,
371 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF
372 | S2EVENT_TX);
375 // Now the packet is already in TX buffer, update flags for NIC
376 if (error == 0)
378 RTLD(
379 APTR packet = np->TxDescArray[nr].addr;
380 bug("[%s] RTL8168_TX_IntF: packet %d @ %p [type = %d] queued for transmission.\n", unit->rtl8168u_name, nr, np->TxDescArray[nr].addr, AROS_BE2WORD(((struct eth_frame *)packet)->eth_packet_type))
383 RTLDP(
384 int j;
385 for (j = 0; j < packet_size; j++) {
386 if ((j%16) == 0)
388 if (j != 0)
390 bug("\n");
392 bug("[%s] RTL8168_TX_IntF: %03x:", unit->rtl8168u_name, j);
394 bug(" %02x", ((unsigned char*)np->TxDescArray[nr].addr)[j]);
396 bug("\n")
399 // Set the ring details for the packet ..
400 np->TxDescArray[nr].opts1 = AROS_LONG2LE(DescOwn | FirstFrag | LastFrag | packet_size | (RingEnd * !((nr + 1) % NUM_TX_DESC)));
401 np->TxDescArray[nr].opts2 = AROS_LONG2LE(0);
403 #warning "TODO: Perhaps set the Tx Poll bit after we leave the while loop .."
404 RTL_W8(base + (TxPoll), NPQ); /* set polling bit */
407 // Reply packet
408 request->ios2_Req.io_Error = error;
409 request->ios2_WireError = wire_error;
410 Disable();
411 Remove((APTR)request);
412 Enable();
413 ReplyMsg((APTR)request);
415 try_count = 0;
417 np->cur_tx++;
418 try_count++;
420 // If we've just run out of free space on the TX queue, stop
421 // it and give up pushing further frames
422 if ( (try_count + 1) >= NUM_TX_DESC)
424 RTLD(bug("[%s] output queue full!. Stopping [count = %d, NUM_TX_DESC = %d\n", unit->rtl8168u_name, try_count, NUM_TX_DESC))
425 netif_stop_queue(unit);
426 proceed = FALSE;
431 /* Was there success? Enable incomming of new packets */
432 if(proceed)
433 unit->rtl8168u_request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
434 else
435 unit->rtl8168u_request_ports[WRITE_QUEUE]->mp_Flags = PA_IGNORE;
437 AROS_USERFUNC_EXIT
441 * Handle timeouts and other strange cases
443 static void RTL8168_TimeoutHandlerF(HIDDT_IRQ_Handler *irq, HIDDT_IRQ_HwInfo *hw)
445 struct RTL8168Unit *unit = (struct RTL8168Unit *) irq->h_Data;
446 struct timeval time;
447 struct Device *TimerBase = unit->rtl8168u_TimerSlowReq->tr_node.io_Device;
449 GetSysTime(&time);
450 //RTLD(bug("[%s] RTL8168_TimeoutHandlerF()\n", unit->rtl8168u_name))
453 * If timeout timer is expected, and time elapsed - regenerate the
454 * interrupt handler
456 if (unit->rtl8168u_toutNEED && (CmpTime(&time, &unit->rtl8168u_toutPOLL ) < 0))
458 unit->rtl8168u_toutNEED = FALSE;
459 //Cause(&unit->rtl8168u_tx_end_int);
463 static void RTL8168_Tx_Cleanup(struct net_device *unit)
465 struct rtl8168_priv *np = unit->rtl8168u_priv;
466 unsigned int dirty_tx, tx_left;
467 struct TypeStats *tracker;
469 dirty_tx = np->dirty_tx;
470 tx_left = np->cur_tx - dirty_tx;
472 while (tx_left > 0) {
473 unsigned int entry = dirty_tx % NUM_TX_DESC;
474 ULONG packet_size, status;
476 status = AROS_LE2LONG(np->TxDescArray[entry].opts1);
478 if (status & DescOwn)
479 break;
481 packet_size = status & 0x3FFF;
482 tracker = FindTypeStats(unit->rtl8168u_device, unit, &unit->rtl8168u_type_trackers, ((struct eth_frame *)np->TxDescArray[entry].addr)->eth_packet_type);
483 if(tracker != NULL)
485 tracker->stats.PacketsSent++;
486 tracker->stats.BytesSent += packet_size;
489 if (status & LastFrag) {
490 RTLD(bug("[%s] RTL8168_Tx_Cleanup: Released buffer %d (%d bytes)\n", unit->rtl8168u_name, entry, packet_size))
491 np->TxDescArray[entry].opts1 = AROS_LONG2LE(RingEnd);
492 np->TxDescArray[entry].addr = NULL;
494 dirty_tx++;
495 tx_left--;
497 if (np->dirty_tx != dirty_tx) {
498 np->dirty_tx = dirty_tx;
500 if (netif_queue_stopped(dev) &&
501 (TX_BUFFS_AVAIL(np) >= MAX_SKB_FRAGS)) {
502 netif_wake_queue(dev);
509 * Interrupt handler called whenever RTL8168 NIC interface generates interrupt.
511 static void RTL8168_IntHandlerF(HIDDT_IRQ_Handler *irq, HIDDT_IRQ_HwInfo *hw)
513 struct RTL8168Unit *unit = (struct RTL8168Unit *) irq->h_Data;
514 struct rtl8168_priv *np = unit->rtl8168u_priv;
515 APTR base = unit->rtl8168u_BaseMem;
516 int status;
517 int handled = 0;
519 int boguscnt = unit->rtl8168u_device->rtl8168b_MaxIntWork;
521 UWORD intr_clean_mask = SYSErr | PCSTimeout | SWInt |
522 LinkChg | RxDescUnavail |
523 TxErr | TxOK | RxErr | RxOK;
525 RTL_W16(base + (IntrMask), 0x0000);
527 RTLD(bug("[%s] RTL8168_IntHandlerF()!!!!!!!\n", unit->rtl8168u_name))
529 do {
530 status = RTL_R16(base + (IntrStatus));
532 /* hotplug/major error/no more work/shared irq */
533 if ((status == 0xFFFF) || !status)
534 break;
536 handled = 1;
538 // if (!netif_running(unit)) {
539 // rtl8168_asic_down(unit);
540 // goto out;
541 // }
543 status &= (np->intr_mask | TxDescUnavail);
544 RTL_W16(base + (IntrStatus), intr_clean_mask);
546 if (!(status & unit->rtl8168u_intr_mask))
547 break;
549 //Work around for rx fifo overflow
550 if (status & RxFIFOOver)
552 RTLD(bug("[%s] RTL8168_IntHandlerF: Rx FIFO overflow occured!\n", unit->rtl8168u_name))
553 if (np->mcfg == CFG_METHOD_1) {
554 /*np->rx_fifo_overflow = 1;
555 netif_stop_queue(unit);
556 udelay(300);
557 rtl8168_rx_clear(np);
558 rtl8168_init_ring(unit);
559 rtl8168_hw_start(unit);*/
560 RTL_W16(base + (IntrStatus), RxFIFOOver);
561 /*netif_wake_queue(unit);
562 np->rx_fifo_overflow = 0;*/
566 if (status & SYSErr) {
567 RTLD(bug("[%s] RTL8168_IntHandlerF: PCI error occured!\n", unit->rtl8168u_name))
568 // rtl8168_pcierr_interrupt(unit);
569 break;
572 if (status & LinkChg)
574 RTLD(bug("[%s] RTL8168_IntHandlerF: Link Change!\n", unit->rtl8168u_name))
575 rtl8168_CheckLinkStatus(unit);
578 if ((status & TxOK) && (status & TxDescUnavail))
580 RTL_W8(base + (TxPoll), NPQ); /* set polling bit */
581 RTL_W16(base + (IntrStatus), TxDescUnavail);
583 /* Rx interrupt */
584 if (status & (RxOK | RxDescUnavail | RxFIFOOver))
586 RTLD(bug("[%s] RTL8168_IntHandlerF: Packet Reception detected!\n", unit->rtl8168u_name))
587 RTL8168_Rx_Process(unit);
588 // rtl8168_rx_interrupt(unit, np, np->mmio_addr, ~(u32)0);
590 /* Tx interrupt */
591 if (status & (TxOK | TxErr))
593 RTLD(bug("[%s] RTL8168_IntHandlerF: Packet Transmission detected!\n", unit->rtl8168u_name))
594 RTL8168_Tx_Cleanup(unit);
596 boguscnt--;
597 } while (boguscnt > 0);
599 if (boguscnt <= 0) {
600 RTLD(bug("[%s] RTL8168_IntHandlerF: Too much work at interrupt!\n", unit->rtl8168u_name))
601 /* Clear all interrupt sources. */
602 RTL_W16(base + (IntrStatus), 0xffff);
605 out:
606 RTL_W16(base + (IntrMask), np->intr_mask);
608 return;
611 VOID CopyPacket(struct RTL8168Base *RTL8168DeviceBase, struct RTL8168Unit *unit,
612 struct IOSana2Req *request, UWORD packet_size, UWORD packet_type,
613 struct eth_frame *buffer)
615 struct Opener *opener;
616 BOOL filtered = FALSE;
617 UBYTE *ptr;
619 RTLD(bug("[%s] CopyPacket(packet @ %x, len = %d)\n", unit->rtl8168u_name, buffer, packet_size))
621 /* Set multicast and broadcast flags */
623 request->ios2_Req.io_Flags &= ~(SANA2IOF_BCAST | SANA2IOF_MCAST);
624 if((*((ULONG *)(buffer->eth_packet_dest)) == 0xffffffff) &&
625 (*((UWORD *)(buffer->eth_packet_dest + 4)) == 0xffff))
627 request->ios2_Req.io_Flags |= SANA2IOF_BCAST;
628 RTLD(bug("[%s] CopyPacket: BROADCAST Flag set\n", unit->rtl8168u_name))
630 else if((buffer->eth_packet_dest[0] & 0x1) != 0)
632 request->ios2_Req.io_Flags |= SANA2IOF_MCAST;
633 RTLD(bug("[%s] CopyPacket: MULTICAST Flag set\n", unit->rtl8168u_name))
636 /* Set source and destination addresses and packet type */
637 CopyMem(buffer->eth_packet_source, request->ios2_SrcAddr, ETH_ADDRESSSIZE);
638 CopyMem(buffer->eth_packet_dest, request->ios2_DstAddr, ETH_ADDRESSSIZE);
639 request->ios2_PacketType = packet_type;
641 /* Adjust for cooked packet request */
643 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
645 packet_size -= ETH_PACKET_DATA;
646 ptr = (UBYTE*)&buffer->eth_packet_data[0];
648 else
650 ptr = (UBYTE*)buffer;
653 request->ios2_DataLength = packet_size;
655 RTLD(bug("[%s] CopyPacket: packet @ %x (%d bytes)\n", unit->rtl8168u_name, ptr, packet_size))
657 /* Filter packet */
659 opener = request->ios2_BufferManagement;
660 if((request->ios2_Req.io_Command == CMD_READ) &&
661 (opener->filter_hook != NULL))
662 if(!CallHookPkt(opener->filter_hook, request, ptr))
664 RTLD(bug("[%s] CopyPacket: packet filtered\n", unit->rtl8168u_name))
665 filtered = TRUE;
668 if(!filtered)
670 /* Copy packet into opener's buffer and reply packet */
671 RTLD(bug("[%s] CopyPacket: opener recieve packet .. ", unit->rtl8168u_name))
672 if(!opener->rx_function(request->ios2_Data, ptr, packet_size))
674 RTLD(bug("ERROR occured!!\n"))
675 request->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
676 request->ios2_WireError = S2WERR_BUFF_ERROR;
677 ReportEvents(LIBBASE, unit, S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF | S2EVENT_RX);
679 else
681 RTLD(bug("SUCCESS!!\n"))
683 Disable();
684 Remove((APTR)request);
685 Enable();
686 ReplyMsg((APTR)request);
687 RTLD(bug("[%s] CopyPacket: opener notified.\n", unit->rtl8168u_name))
691 BOOL AddressFilter(struct RTL8168Base *RTL8168DeviceBase, struct RTL8168Unit *unit, UBYTE *address)
693 struct AddressRange *range, *tail;
694 BOOL accept = TRUE;
695 ULONG address_left;
696 UWORD address_right;
698 /* Check whether address is unicast/broadcast or multicast */
700 address_left = AROS_BE2LONG(*((ULONG *)address));
701 address_right = AROS_BE2WORD(*((UWORD *)(address + 4)));
703 if((address_left & 0x01000000) != 0 &&
704 !(address_left == 0xffffffff && address_right == 0xffff))
706 /* Check if this multicast address is wanted */
708 range = (APTR)unit->rtl8168u_multicast_ranges.mlh_Head;
709 tail = (APTR)&unit->rtl8168u_multicast_ranges.mlh_Tail;
710 accept = FALSE;
712 while((range != tail) && !accept)
714 if((address_left > range->lower_bound_left ||
715 (address_left == range->lower_bound_left &&
716 address_right >= range->lower_bound_right)) &&
717 (address_left < range->upper_bound_left ||
718 (address_left == range->upper_bound_left &&
719 address_right <= range->upper_bound_right)))
720 accept = TRUE;
721 range = (APTR)range->node.mln_Succ;
724 if(!accept)
725 unit->rtl8168u_special_stats[S2SS_ETHERNET_BADMULTICAST & 0xffff]++;
727 return accept;
731 * Unit process
733 AROS_UFH3(void, RTL8168_Schedular,
734 AROS_UFHA(STRPTR, argPtr, A0),
735 AROS_UFHA(ULONG, argSize, D0),
736 AROS_UFHA(struct ExecBase *, SysBase, A6))
738 AROS_USERFUNC_INIT
740 struct Task *taskSelf = FindTask(NULL);
741 struct RTL8168Startup *sm_UD = taskSelf->tc_UserData;
742 struct RTL8168Unit *unit = sm_UD->rtl8168sm_Unit;
744 LIBBASETYPEPTR LIBBASE = unit->rtl8168u_device;
745 struct MsgPort *reply_port, *input;
746 APTR BattClockBase;
748 RTLD(bug("[%s] RTL8168_Schedular()\n", taskSelf->tc_Node.ln_Name))
749 RTLD(bug("[%s] RTL8168_Schedular: Setting up device '%s'\n", taskSelf->tc_Node.ln_Name, unit->rtl8168u_name))
751 if ((reply_port = CreateMsgPort()) == NULL)
753 RTLD(bug("[%s] RTL8168_Schedular: Failed to create Reply message port\n", taskSelf->tc_Node.ln_Name))
756 if ((input = CreateMsgPort()) == NULL)
758 RTLD(bug("[%s] RTL8168_Schedular: Failed to create Input message port\n", taskSelf->tc_Node.ln_Name))
761 unit->rtl8168u_input_port = input;
763 /* Randomize the generator with current time */
764 if ((BattClockBase = OpenResource("battclock.resource")) != NULL)
766 srandom(ReadBattClock());
769 if ((unit->rtl8168u_TimerSlowPort = CreateMsgPort()) != NULL)
771 unit->rtl8168u_TimerSlowReq = (struct timerequest *)
772 CreateIORequest((struct MsgPort *)unit->rtl8168u_TimerSlowPort, sizeof(struct timerequest));
774 if (unit->rtl8168u_TimerSlowReq)
776 if (!OpenDevice("timer.device", UNIT_MICROHZ,
777 (struct IORequest *)unit->rtl8168u_TimerSlowReq, 0))
779 struct Message *msg = AllocVec(sizeof(struct Message), MEMF_PUBLIC|MEMF_CLEAR);
780 ULONG sigset;
782 RTLD(bug("[%s] RTL8168_Schedular: Got MICROHZ unit of timer.device\n", taskSelf->tc_Node.ln_Name))
784 unit->initialize(unit);
786 msg->mn_ReplyPort = reply_port;
787 msg->mn_Length = sizeof(struct Message);
789 RTLD(bug("[%s] RTL8168_Schedular: Setup complete. Sending handshake\n", taskSelf->tc_Node.ln_Name))
790 PutMsg(sm_UD->rtl8168sm_SyncPort, msg);
791 WaitPort(reply_port);
792 GetMsg(reply_port);
794 FreeVec(msg);
796 RTLD(bug("[%s] RTL8168_Schedular: entering forever loop ... \n", taskSelf->tc_Node.ln_Name))
798 unit->rtl8168u_signal_0 = AllocSignal(-1);
799 unit->rtl8168u_signal_1 = AllocSignal(-1);
800 unit->rtl8168u_signal_2 = AllocSignal(-1);
801 unit->rtl8168u_signal_3 = AllocSignal(-1);
803 sigset = 1 << input->mp_SigBit |
804 1 << unit->rtl8168u_signal_0 |
805 1 << unit->rtl8168u_signal_1 |
806 1 << unit->rtl8168u_signal_2 |
807 1 << unit->rtl8168u_signal_3;
808 for(;;)
810 ULONG recvd = Wait(sigset);
811 if (recvd & unit->rtl8168u_signal_0)
814 * Shutdown process. Driver should close everything
815 * already and waits for our process to complete. Free
816 * memory allocared here and kindly return.
818 unit->deinitialize(unit);
819 CloseDevice((struct IORequest *)unit->rtl8168u_TimerSlowReq);
820 DeleteIORequest((struct IORequest *)unit->rtl8168u_TimerSlowReq);
821 DeleteMsgPort(unit->rtl8168u_TimerSlowPort);
822 DeleteMsgPort(input);
823 DeleteMsgPort(reply_port);
825 RTLD(bug("[%s] RTL8168_Schedular: Process shutdown.\n", taskSelf->tc_Node.ln_Name))
826 return;
828 else if (recvd & (1 << input->mp_SigBit))
830 struct IOSana2Req *io;
832 /* Handle incoming transactions */
833 while ((io = (struct IOSana2Req *)GetMsg(input)) != NULL)
835 RTLD(bug("[%s] RTL8168_Schedular: Handle incomming transaction.\n", taskSelf->tc_Node.ln_Name))
836 ObtainSemaphore(&unit->rtl8168u_unit_lock);
837 handle_request(LIBBASE, io);
840 else
842 RTLD(bug("[%s] RTL8168_Schedular: Handle incomming signal.\n", taskSelf->tc_Node.ln_Name))
843 /* Handle incoming signals */
850 AROS_USERFUNC_EXIT
853 static struct AddressRange *FindMulticastRange(LIBBASETYPEPTR LIBBASE, struct RTL8168Unit *unit,
854 ULONG lower_bound_left, UWORD lower_bound_right, ULONG upper_bound_left, UWORD upper_bound_right)
856 struct AddressRange *range, *tail;
857 BOOL found = FALSE;
859 range = (APTR)unit->rtl8168u_multicast_ranges.mlh_Head;
860 tail = (APTR)&unit->rtl8168u_multicast_ranges.mlh_Tail;
862 while((range != tail) && !found)
864 if((lower_bound_left == range->lower_bound_left) &&
865 (lower_bound_right == range->lower_bound_right) &&
866 (upper_bound_left == range->upper_bound_left) &&
867 (upper_bound_right == range->upper_bound_right))
868 found = TRUE;
869 else
870 range = (APTR)range->node.mln_Succ;
873 if(!found)
874 range = NULL;
876 return range;
879 BOOL AddMulticastRange(LIBBASETYPEPTR LIBBASE, struct RTL8168Unit *unit, const UBYTE *lower_bound,
880 const UBYTE *upper_bound)
882 struct AddressRange *range;
883 ULONG lower_bound_left, upper_bound_left;
884 UWORD lower_bound_right, upper_bound_right;
886 lower_bound_left = AROS_BE2LONG(*((ULONG *)lower_bound));
887 lower_bound_right = AROS_BE2WORD(*((UWORD *)(lower_bound + 4)));
888 upper_bound_left = AROS_BE2LONG(*((ULONG *)upper_bound));
889 upper_bound_right = AROS_BE2WORD(*((UWORD *)(upper_bound + 4)));
891 range = FindMulticastRange(LIBBASE, unit, lower_bound_left, lower_bound_right,
892 upper_bound_left, upper_bound_right);
894 if(range != NULL)
895 range->add_count++;
896 else
898 range = AllocMem(sizeof(struct AddressRange), MEMF_PUBLIC);
899 if(range != NULL)
901 range->lower_bound_left = lower_bound_left;
902 range->lower_bound_right = lower_bound_right;
903 range->upper_bound_left = upper_bound_left;
904 range->upper_bound_right = upper_bound_right;
905 range->add_count = 1;
907 Disable();
908 AddTail((APTR)&unit->rtl8168u_multicast_ranges, (APTR)range);
909 Enable();
911 if (unit->rtl8168u_range_count++ == 0)
913 unit->rtl8168u_flags |= IFF_ALLMULTI;
914 unit->set_multicast(unit);
919 return range != NULL;
922 BOOL RemMulticastRange(LIBBASETYPEPTR LIBBASE, struct RTL8168Unit *unit, const UBYTE *lower_bound, const UBYTE *upper_bound)
924 struct AddressRange *range;
925 ULONG lower_bound_left, upper_bound_left;
926 UWORD lower_bound_right, upper_bound_right;
928 lower_bound_left = AROS_BE2LONG(*((ULONG *)lower_bound));
929 lower_bound_right = AROS_BE2WORD(*((UWORD *)(lower_bound + 4)));
930 upper_bound_left = AROS_BE2LONG(*((ULONG *)upper_bound));
931 upper_bound_right = AROS_BE2WORD(*((UWORD *)(upper_bound + 4)));
933 range = FindMulticastRange(LIBBASE, unit, lower_bound_left, lower_bound_right,
934 upper_bound_left, upper_bound_right);
936 if(range != NULL)
938 if(--range->add_count == 0)
940 Disable();
941 Remove((APTR)range);
942 Enable();
943 FreeMem(range, sizeof(struct AddressRange));
945 if (--unit->rtl8168u_range_count == 0)
947 unit->rtl8168u_flags &= ~IFF_ALLMULTI;
948 unit->set_multicast(unit);
952 return range != NULL;
956 * Create new RTL8168 ethernet device unit
958 struct RTL8168Unit *CreateUnit(struct RTL8168Base *RTL8168DeviceBase, OOP_Object *pciDevice, IPTR CardRevision)
960 struct RTL8168Unit *unit;
961 BOOL success = TRUE;
962 int i;
964 #if defined(RTL_DEBUG)
965 BOOL doDebug = TRUE;
966 #else
967 #warning "TODO: Get option to debug from somewhere .."
968 BOOL doDebug = FALSE;
969 #endif
971 if (doDebug)
973 bug("[rtl8168] CreateUnit()\n");
976 if ((unit = AllocMem(sizeof(struct RTL8168Unit), MEMF_PUBLIC | MEMF_CLEAR)) != NULL)
978 IPTR DeviceID, mmiobase, mmiolen, type;
979 OOP_Object *driver;
980 BOOL mmioerror = FALSE;
982 if (doDebug)
983 unit->rtl8168u_flags |= IFF_DEBUG;
985 unit->rtl8168u_UnitNum = RTL8168DeviceBase->rtl8168b_UnitCount++;
987 unit->rtl8168u_Sana2Info.HardwareType = S2WireType_Ethernet;
988 unit->rtl8168u_Sana2Info.MTU = ETH_MTU;
989 unit->rtl8168u_Sana2Info.AddrFieldSize = 8 * ETH_ADDRESSSIZE;
991 unit->rtl8168u_intr_mask = SYSErr | LinkChg | RxDescUnavail | TxErr | TxOK | RxErr | RxOK;
993 if ((unit->rtl8168u_name = AllocVec(8 + (unit->rtl8168u_UnitNum/10) + 2, MEMF_CLEAR|MEMF_PUBLIC)) == NULL)
995 FreeMem(unit, sizeof(struct RTL8168Unit));
996 return NULL;
998 sprintf((char *)unit->rtl8168u_name, "rtl8168.%d", unit->rtl8168u_UnitNum);
1000 RTLD(bug("[rtl8168] CreateUnit: Unit allocated @ 0x%p\n", unit))
1002 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Driver, (APTR)&driver);
1004 unit->rtl8168u_device = RTL8168DeviceBase;
1005 unit->rtl8168u_PCIDevice = pciDevice;
1006 unit->rtl8168u_PCIDriver = driver;
1008 unit->rtl8168u_mtu = unit->rtl8168u_Sana2Info.MTU;
1010 InitSemaphore(&unit->rtl8168u_unit_lock);
1011 NEWLIST(&unit->rtl8168u_Openers);
1012 NEWLIST(&unit->rtl8168u_multicast_ranges);
1013 NEWLIST(&unit->rtl8168u_type_trackers);
1015 OOP_GetAttr(pciDevice, aHidd_PCIDevice_INTLine, &unit->rtl8168u_IRQ);
1016 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Base0, &unit->rtl8168u_BaseIO);
1017 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Base2, &mmiobase);
1018 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Size2, &mmiolen);
1019 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Type2, &type);
1021 RTLD(bug("[%s] CreateUnit: INT:%d, base0:0x%p, base2:0x%p, size2:%d\n", unit->rtl8168u_name,
1022 unit->rtl8168u_IRQ, unit->rtl8168u_BaseIO,
1023 mmiobase, mmiolen))
1025 if (type & ADDRF_IO)
1027 RTLD(bug("[%s] CreateUnit: MMIO Region of wrong type!\n", unit->rtl8168u_name))
1028 mmioerror = TRUE;
1031 if (mmiolen < R8168_REGS_SIZE)
1033 RTLD(bug("[%s] CreateUnit: Invalid MMIO Reg size (%d, expected %d)\n", unit->rtl8168u_name,
1034 mmiolen,
1035 R8168_REGS_SIZE))
1036 mmioerror = TRUE;
1039 if (mmioerror)
1041 FreeMem(unit->rtl8168u_name, 8 + (unit->rtl8168u_UnitNum/10) + 2);
1042 FreeMem(unit, sizeof(struct RTL8168Unit));
1043 return NULL;
1046 #warning "TODO: how do we set memory write invalidate for PCI devices on AROS?"
1048 unit->rtl8168u_SizeMem = R8168_REGS_SIZE;
1049 unit->rtl8168u_BaseMem = (IPTR)HIDD_PCIDriver_MapPCI(driver, (APTR)mmiobase, unit->rtl8168u_SizeMem);
1051 if (unit->rtl8168u_BaseMem != NULL)
1053 struct TagItem attrs[] = {
1054 { aHidd_PCIDevice_isIO, TRUE },
1055 { aHidd_PCIDevice_isMEM, TRUE },
1056 { aHidd_PCIDevice_isMaster, TRUE },
1057 { TAG_DONE, 0 },
1059 OOP_SetAttrs(pciDevice, (struct TagItem *)&attrs);
1061 RTLD(bug("[%s] CreateUnit: PCI_BaseMem @ 0x%p\n", unit->rtl8168u_name, unit->rtl8168u_BaseMem))
1063 unit->rtl8168u_DelayPort.mp_SigBit = SIGB_SINGLE;
1064 unit->rtl8168u_DelayPort.mp_Flags = PA_SIGNAL;
1065 unit->rtl8168u_DelayPort.mp_SigTask = FindTask(NULL);
1066 unit->rtl8168u_DelayPort.mp_Node.ln_Type = NT_MSGPORT;
1067 NEWLIST(&unit->rtl8168u_DelayPort.mp_MsgList);
1069 unit->rtl8168u_DelayReq.tr_node.io_Message.mn_ReplyPort = &unit->rtl8168u_DelayPort;
1070 unit->rtl8168u_DelayReq.tr_node.io_Message.mn_Length = sizeof(struct timerequest);
1072 OpenDevice((STRPTR)"timer.device", UNIT_MICROHZ, (struct IORequest *)&unit->rtl8168u_DelayReq, 0);
1074 if ((unit->rtl8168u_priv = AllocMem(sizeof(struct rtl8168_priv), MEMF_PUBLIC|MEMF_CLEAR)) != NULL)
1076 unit->rtl8168u_priv->pci_dev = unit;
1077 InitSemaphore(&unit->rtl8168u_priv->lock);
1079 unit->rtl8168u_irqhandler = AllocMem(sizeof(HIDDT_IRQ_Handler), MEMF_PUBLIC|MEMF_CLEAR);
1080 unit->rtl8168u_touthandler = AllocMem(sizeof(HIDDT_IRQ_Handler), MEMF_PUBLIC|MEMF_CLEAR);
1082 if ((unit->rtl8168u_irqhandler != NULL)
1083 && (unit->rtl8168u_touthandler != NULL))
1085 struct Message *msg;
1087 unit->rtl8168u_irqhandler->h_Node.ln_Pri = 100;
1088 unit->rtl8168u_irqhandler->h_Node.ln_Name = LIBBASE->rtl8168b_Device.dd_Library.lib_Node.ln_Name;
1089 unit->rtl8168u_irqhandler->h_Code = RTL8168_IntHandlerF;
1090 unit->rtl8168u_irqhandler->h_Data = unit;
1092 unit->rtl8168u_touthandler->h_Node.ln_Pri = 100;
1093 unit->rtl8168u_touthandler->h_Node.ln_Name = LIBBASE->rtl8168b_Device.dd_Library.lib_Node.ln_Name;
1094 unit->rtl8168u_touthandler->h_Code = RTL8168_TimeoutHandlerF;
1095 unit->rtl8168u_touthandler->h_Data = unit;
1097 unit->rtl8168u_rx_int.is_Node.ln_Name = unit->rtl8168u_name;
1098 //unit->rtl8168u_rx_int.is_Code = RTL8168_RX_IntF;
1099 unit->rtl8168u_rx_int.is_Data = unit;
1101 unit->rtl8168u_tx_int.is_Node.ln_Name = unit->rtl8168u_name;
1102 unit->rtl8168u_tx_int.is_Code = RTL8168_TX_IntF;
1103 unit->rtl8168u_tx_int.is_Data = unit;
1105 for (i=0; i < REQUEST_QUEUE_COUNT; i++)
1107 struct MsgPort *port = AllocMem(sizeof(struct MsgPort), MEMF_PUBLIC | MEMF_CLEAR);
1108 unit->rtl8168u_request_ports[i] = port;
1110 if (port == NULL) success = FALSE;
1112 if (success)
1114 NEWLIST(&port->mp_MsgList);
1115 port->mp_Flags = PA_IGNORE;
1116 port->mp_SigTask = &unit->rtl8168u_tx_int;
1120 unit->rtl8168u_request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
1122 if (success)
1124 struct RTL8168Startup *sm_UD;
1125 UBYTE tmpbuff[100];
1127 if ((sm_UD = AllocMem(sizeof(struct RTL8168Startup), MEMF_PUBLIC | MEMF_CLEAR)) != NULL)
1129 sprintf((char *)tmpbuff, RTL8168_TASK_NAME, unit->rtl8168u_name);
1131 sm_UD->rtl8168sm_SyncPort = CreateMsgPort();
1132 sm_UD->rtl8168sm_Unit = unit;
1134 rtl8168nic_get_functions(unit);
1136 unit->rtl8168u_Process = CreateNewProcTags(
1137 NP_Entry, (IPTR)RTL8168_Schedular,
1138 NP_Name, tmpbuff,
1139 NP_Synchronous , FALSE,
1140 NP_Priority, 0,
1141 NP_UserData, (IPTR)sm_UD,
1142 NP_StackSize, 140960,
1143 TAG_DONE);
1145 WaitPort(sm_UD->rtl8168sm_SyncPort);
1146 msg = GetMsg(sm_UD->rtl8168sm_SyncPort);
1147 ReplyMsg(msg);
1148 DeleteMsgPort(sm_UD->rtl8168sm_SyncPort);
1149 FreeMem(sm_UD, sizeof(struct RTL8168Startup));
1151 RTLD(bug("[%s] CreateUnit: Device Initialised. Unit %d @ %p\n", unit->rtl8168u_name, unit->rtl8168u_UnitNum, unit))
1152 return unit;
1155 else
1157 RTLD(bug("[%s] ERRORS occured during Device setup - ABORTING\n", unit->rtl8168u_name))
1162 else
1164 RTLD(bug("[rtl8168] PANIC! Couldn't get MMIO area. Aborting\n"))
1167 else if (doDebug)
1169 bug("[rtl8168] CreateUnit: Failed to Allocate Unit storage!\n");
1170 return NULL;
1172 DeleteUnit(RTL8168DeviceBase, unit);
1173 return NULL;
1177 * DeleteUnit - removes selected unit. Frees all resources and structures.
1179 * The caller should be sure, that given unit is really ready to be freed.
1182 void DeleteUnit(struct RTL8168Base *RTL8168DeviceBase, struct RTL8168Unit *Unit)
1184 int i;
1185 if (Unit)
1187 if (Unit->rtl8168u_Process)
1189 Signal(&Unit->rtl8168u_Process->pr_Task, Unit->rtl8168u_signal_0);
1192 for (i=0; i < REQUEST_QUEUE_COUNT; i++)
1194 if (Unit->rtl8168u_request_ports[i] != NULL)
1195 FreeMem(Unit->rtl8168u_request_ports[i], sizeof(struct MsgPort));
1197 Unit->rtl8168u_request_ports[i] = NULL;
1200 if (Unit->rtl8168u_irqhandler)
1202 FreeMem(Unit->rtl8168u_irqhandler, sizeof(HIDDT_IRQ_Handler));
1205 if (Unit->rtl8168u_priv)
1207 FreeMem(Unit->rtl8168u_priv, sizeof(struct rtl8168_priv));
1208 Unit->rtl8168u_priv = NULL;
1211 if (Unit->rtl8168u_BaseMem)
1213 HIDD_PCIDriver_UnmapPCI(Unit->rtl8168u_PCIDriver,
1214 (APTR)Unit->rtl8168u_BaseMem,
1215 Unit->rtl8168u_SizeMem);
1218 FreeMem(Unit, sizeof(struct RTL8168Unit));