Fixed binary search: no more infinite loops when vendor is unknown.
[tangerine.git] / workbench / devs / networks / rtl8139 / unit.c
blob37785e932d7c7704b74acd897e1a0923b9a93f38
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 <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 "rtl8139.h"
50 #include "unit.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;
59 struct List *list;
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 */
66 Disable();
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);
79 Enable();
81 return;
84 struct TypeStats *FindTypeStats(struct RTL8139Base *RTL8139DeviceBase, struct RTL8139Unit *unit,
85 struct MinList *list, ULONG packet_type)
87 struct TypeStats *stats, *tail;
88 BOOL found = FALSE;
90 stats = (APTR)list->mlh_Head;
91 tail = (APTR)&list->mlh_Tail;
93 while(stats != tail && !found)
95 if(stats->packet_type == packet_type)
96 found = TRUE;
97 else
98 stats = (APTR)stats->node.mln_Succ;
101 if(!found)
102 stats = NULL;
104 return stats;
107 void FlushUnit(LIBBASETYPEPTR LIBBASE, struct RTL8139Unit *unit, UBYTE last_queue, BYTE error)
109 struct IORequest *request;
110 UBYTE i;
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;
152 ULONG packet_type;
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))
186 rx_status = 0;
189 if (rx_status & RxTooLong)
191 RTLD(bug("[%s] RTL8139_RX_Process: Oversized Ethernet Frame\n", unit->rtl8139u_name))
194 /* Reset the reciever */
195 np->cur_rx = 0;
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 */
208 is_orphan = TRUE;
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!"
218 RTLD( int j;
219 for (j=0; j<64; j++) {
220 if ((j%16) == 0)
221 bug("\n%03x:", j);
223 bug(" %02x", ((unsigned char*)frame)[j]);
225 bug("\n");)
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;
242 accepted = FALSE;
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);
253 accepted = TRUE;
255 request = (struct IOSana2Req *)request->ios2_Req.io_Message.mn_Node.ln_Succ;
258 if(accepted)
259 is_orphan = FALSE;
261 opener = (APTR)opener->node.mln_Succ;
264 /* If packet was unwanted, give it to S2_READORPHAN request */
265 if(is_orphan)
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);
281 if(tracker != NULL)
283 tracker->stats.PacketsReceived++;
284 tracker->stats.BytesReceived += len;
287 unit->rtl8139u_stats.PacketsReceived++;
289 else
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))
304 AROS_USERFUNC_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 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;
319 UBYTE *buffer;
320 ULONG wire_error=0;
321 BYTE error;
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;
333 error = 0;
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;
352 else
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
364 | S2EVENT_TX);
367 /* Now the packet is already in TX buffer, update flags for NIC */
368 if (error == 0)
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)))
372 RTLD( int j;
373 for (j=0; j<64; j++) {
374 if ((j%16) == 0)
375 bug("\n%03x:", j);
376 bug(" %02x", ((unsigned char*)np->tx_buf[nr])[j]);
378 bug("\n");)
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));
385 /* Reply packet */
386 request->ios2_Req.io_Error = error;
387 request->ios2_WireError = wire_error;
388 Disable();
389 Remove((APTR)request);
390 Enable();
391 ReplyMsg((APTR)request);
393 /* Update statistics */
394 if(error == 0)
396 tracker = FindTypeStats(LIBBASE, unit, &unit->rtl8139u_type_trackers, request->ios2_PacketType);
398 if(tracker != NULL)
400 tracker->stats.PacketsSent++;
401 tracker->stats.BytesSent += packet_size;
404 try_count = 0;
406 np->tx_current++;
407 try_count++;
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);
416 proceed = FALSE;
418 } /* while */
421 /* Was there success? Enable incomming of new packets */
422 if(proceed)
423 unit->rtl8139u_request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
424 else
425 unit->rtl8139u_request_ports[WRITE_QUEUE]->mp_Flags = PA_IGNORE;
427 AROS_USERFUNC_EXIT
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;
436 struct timeval time;
437 struct Device *TimerBase = unit->rtl8139u_TimerSlowReq->tr_node.io_Device;
439 GetSysTime(&time);
440 //RTLD(bug("[%s] RTL8139_TimeoutHandlerF()\n", unit->rtl8139u_name))
443 * If timeout timer is expected, and time elapsed - regenerate the
444 * interrupt handler
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
459 * filter function).
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))
471 while (1)
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;
487 } else {
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))
498 break;
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;
533 else
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;
542 else
544 RTLD(bug("[%s] RTL8139_IntHandlerF: Packet %d Sent Successfully\n", unit->rtl8139u_name, tx_cur))
547 np->tx_pbuf[tx_cur] = NULL;
548 if (transmit_error)
549 dirty_tx++;
551 else
553 RTLD(bug("[%s] RTL8139_IntHandlerF: Packet %d still in transmission\n", unit->rtl8139u_name, tx_cur))
556 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);
571 break;
575 return;
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;
584 UBYTE *ptr;
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];
615 else
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))
624 /* Filter packet */
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))
632 filtered = TRUE;
635 if(!filtered)
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);
646 else
648 RTLD(bug("SUCCESS!!\n"))
650 Disable();
651 Remove((APTR)request);
652 Enable();
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;
661 BOOL accept = TRUE;
662 ULONG address_left;
663 UWORD address_right;
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;
677 accept = FALSE;
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)))
687 accept = TRUE;
688 range = (APTR)range->node.mln_Succ;
691 if(!accept)
692 unit->rtl8139u_special_stats[S2SS_ETHERNET_BADMULTICAST & 0xffff]++;
694 return accept;
698 * Unit process
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))
705 AROS_USERFUNC_INIT
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;
713 APTR BattClockBase;
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);
747 ULONG sigset;
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);
759 GetMsg(reply_port);
761 FreeVec(msg);
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;
775 for(;;)
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))
793 return;
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);
807 else
809 RTLD(bug("[%s] RTL8139_Schedular: Handle incomming signal.\n", taskSelf->tc_Node.ln_Name))
810 /* Handle incoming signals */
817 AROS_USERFUNC_EXIT
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;
826 BOOL success = TRUE;
827 int i;
829 #if defined(RTL_DEBUG)
830 BOOL doDebug = TRUE;
831 #else
832 #warning "TODO: Get option to debug from somewhere .."
833 BOOL doDebug = FALSE;
834 #endif
836 if (doDebug)
838 bug("[rtl8139] CreateUnit()\n");
841 if ((unit = AllocMem(sizeof(struct RTL8139Unit), MEMF_PUBLIC | MEMF_CLEAR)) != NULL)
843 IPTR DeviceID, base, len;
844 OOP_Object *driver;
846 if (doDebug)
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));
858 return NULL;
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,
890 base, len))
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 },
901 { TAG_DONE, 0 },
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)
921 struct Message *msg;
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;
948 if (success)
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;
958 if (success)
960 struct RTL8139Startup *sm_UD;
961 UBYTE tmpbuff[100];
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,
972 NP_Name, tmpbuff,
973 NP_Synchronous , FALSE,
974 NP_Priority, 0,
975 NP_UserData, (IPTR)sm_UD,
976 NP_StackSize, 140960,
977 TAG_DONE);
979 WaitPort(sm_UD->rtl8139sm_SyncPort);
980 msg = GetMsg(sm_UD->rtl8139sm_SyncPort);
981 ReplyMsg(msg);
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))
986 return unit;
989 else
991 RTLD(bug("[%s] ERRORS occured during Device setup - ABORTING\n", unit->rtl8139u_name))
996 else
998 RTLD(bug("[rtl8139] PANIC! Couldn't get MMIO area. Aborting\n"))
1001 else if (doDebug)
1003 bug("[rtl8139] CreateUnit: Failed to Allocate Unit storage!\n");
1004 return NULL;
1006 DeleteUnit(RTL8139DeviceBase, unit);
1007 return NULL;
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)
1018 int i;
1019 if (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;
1060 BOOL found = FALSE;
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))
1071 found = TRUE;
1072 else
1073 range = (APTR)range->node.mln_Succ;
1076 if(!found)
1077 range = NULL;
1079 return range;
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);
1097 if(range != NULL)
1098 range->add_count++;
1099 else
1101 range = AllocMem(sizeof(struct AddressRange), MEMF_PUBLIC);
1102 if(range != NULL)
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;
1110 Disable();
1111 AddTail((APTR)&unit->rtl8139u_multicast_ranges, (APTR)range);
1112 Enable();
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);
1139 if(range != NULL)
1141 if(--range->add_count == 0)
1143 Disable();
1144 Remove((APTR)range);
1145 Enable();
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;