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