Fixed binary search: no more infinite loops when vendor is unknown.
[tangerine.git] / workbench / devs / networks / e1000 / unit.c
blob8e4bac5190b077409c4a125f5c9291d4f72b2e1e
1 /*
2 * $Id$
3 */
4 /*
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 MA 02111-1307, USA.
21 #include <exec/types.h>
22 #include <exec/resident.h>
23 #include <exec/io.h>
24 #include <exec/ports.h>
25 #include <exec/errors.h>
27 #include <aros/io.h>
29 #include <devices/sana2.h>
30 #include <devices/sana2specialstats.h>
31 #include <devices/newstyle.h>
32 #include <devices/timer.h>
34 #include <utility/utility.h>
35 #include <utility/tagitem.h>
36 #include <utility/hooks.h>
38 #include <proto/exec.h>
39 #include <proto/dos.h>
40 #include <proto/battclock.h>
41 #include <proto/oop.h>
42 #include <proto/timer.h>
43 #include <proto/utility.h>
45 #include <stdlib.h>
46 #include <stdio.h>
48 #include "e1000_hw.h"
49 #include "e1000_api.h"
50 #include "e1000_defines.h"
51 #include "unit.h"
52 #include LC_LIBDEFS_FILE
55 * Report incoming events to all hyphotetical event receivers
57 VOID ReportEvents(struct e1000Base *e1KBase, struct e1000Unit *unit, ULONG events)
59 struct IOSana2Req *request, *tail, *next_request;
60 struct List *list;
62 list = &unit->e1ku_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 e1000Base *e1KBase, struct e1000Unit *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 e1000Unit *unit, UBYTE last_queue, BYTE error)
110 struct IORequest *request;
111 UBYTE i;
112 struct Opener *opener, *tail;
114 D(bug("[%s] unit.FlushUnit\n", unit->e1ku_name));
116 /* Abort queued operations */
118 for (i=0; i <= last_queue; i++)
120 while ((request = (APTR)GetMsg(unit->e1ku_request_ports[i])) != NULL)
122 request->io_Error = IOERR_ABORTED;
123 ReplyMsg((struct Message *)request);
127 opener = (APTR)unit->e1ku_Openers.mlh_Head;
128 tail = (APTR)&unit->e1ku_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;
144 * Interrupt generated by Cause() to push new packets into the NIC interface
146 AROS_UFH3(void, e1000func_TX_Int,
147 AROS_UFHA(struct e1000Unit *, unit, A1),
148 AROS_UFHA(APTR, dummy, A5),
149 AROS_UFHA(struct ExecBase *,SysBase, A6))
151 AROS_USERFUNC_INIT
153 struct e1000Base *e1KBase = unit->e1ku_device;
154 struct e1000_tx_ring *tx_ring = &unit->e1ku_txRing[0];
155 struct e1000_tx_desc *tx_desc = NULL;
156 struct e1000_buffer *buffer_info;
157 struct eth_frame *frame;
158 struct IOSana2Req *request;
159 struct Opener *opener;
160 struct MsgPort *port;
161 struct TypeStats *tracker;
162 int tx_flags = E1000_TX_FLAGS_IPV4;
163 unsigned int i;
164 ULONG txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
165 UWORD packet_size, data_size;
166 UBYTE *buffer, error;
167 ULONG wire_error=0;
168 BOOL proceed = FALSE;
170 D(bug("[%s]: ## e1000func_TX_Int()\n", unit->e1ku_name));
172 if (tx_flags & E1000_TX_FLAGS_TSO) {
173 txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D |
174 E1000_TXD_CMD_TSE;
175 txd_upper |= E1000_TXD_POPTS_TXSM << 8;
177 if (tx_flags & E1000_TX_FLAGS_IPV4)
178 txd_upper |= E1000_TXD_POPTS_IXSM << 8;
181 if (tx_flags & E1000_TX_FLAGS_CSUM) {
182 txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
183 txd_upper |= E1000_TXD_POPTS_TXSM << 8;
186 if (tx_flags & E1000_TX_FLAGS_VLAN) {
187 txd_lower |= E1000_TXD_CMD_VLE;
188 txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK);
191 i = tx_ring->next_to_use;
193 proceed = TRUE; /* Success by default */
194 port = unit->e1ku_request_ports[WRITE_QUEUE];
196 D(bug("[%s]: ## e1000func_TX_Int: nxt to use = %d, write queue port @ %p\n", unit->e1ku_name, i, port));
198 while(proceed && (!IsMsgPortEmpty(port)))
200 error = 0;
201 request = (APTR)port->mp_MsgList.lh_Head;
202 data_size = packet_size = request->ios2_DataLength;
204 opener = (APTR)request->ios2_BufferManagement;
206 buffer_info = &tx_ring->buffer_info[i];
208 if ((buffer_info->buffer = AllocMem(ETH_MAXPACKETSIZE, MEMF_PUBLIC|MEMF_CLEAR)) != NULL)
210 frame = buffer_info->buffer;
212 if ((buffer_info->dma = HIDD_PCIDriver_CPUtoPCI(unit->e1ku_PCIDriver, buffer_info->buffer)) == NULL)
214 D(bug("[%s]: e1000func_TX_Int: Failed to Map Tx DMA buffer\n", unit->e1ku_name));
216 else
218 D(bug("[%s]: e1000func_TX_Int: Tx DMA buffer %d @ %p\n", unit->e1ku_name, i, buffer_info->dma));
221 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
223 packet_size += ETH_PACKET_DATA;
224 CopyMem(request->ios2_DstAddr, frame->eth_packet_dest, ETH_ADDRESSSIZE);
225 CopyMem(unit->e1ku_dev_addr, frame->eth_packet_source, ETH_ADDRESSSIZE);
226 frame->eth_packet_type = AROS_WORD2BE(request->ios2_PacketType);
228 buffer = frame->eth_packet_data;
230 else
231 buffer = (UBYTE *)frame;
233 if (!opener->tx_function(buffer, request->ios2_Data, data_size))
235 error = S2ERR_NO_RESOURCES;
236 wire_error = S2WERR_BUFF_ERROR;
237 ReportEvents(LIBBASE, unit,
238 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF
239 | S2EVENT_TX);
242 /* Now the packet is already in TX buffer, update flags for NIC */
243 if (error == 0)
245 Disable();
246 D(bug("[%s]: e1000func_TX_Int: packet %d [type = %d] queued for transmission.\n", unit->e1ku_name, i, AROS_BE2WORD(frame->eth_packet_type)));
248 /* DEBUG? Dump frame if so */
249 #ifdef DEBUG
251 int j;
252 D(bug("[%s]: Tx Buffer %d Packet Dump -:", unit->e1ku_name, i));
253 for (j=0; j<64; j++) {
254 if ((j%16) == 0)
255 D(bug("\n[%s]: %03x:", unit->e1ku_name, j));
256 D(bug(" %02x", ((unsigned char*)frame)[j]));
258 D(bug("\n"));
260 #endif
261 Enable();
263 /* Set the ring details for the packet .. */
264 buffer_info->length = packet_size;
266 tx_desc = E1000_TX_DESC(tx_ring, i);
267 tx_desc->buffer_addr = (UQUAD)buffer_info->dma;
268 tx_desc->lower.data = AROS_WORD2LE(txd_lower | buffer_info->length);
269 tx_desc->upper.data = AROS_WORD2LE(txd_upper);
270 tx_desc->lower.data |= AROS_WORD2LE(unit->txd_cmd);
271 MMIO_W32((APTR)(((struct e1000_hw *)unit->e1ku_Private00)->hw_addr + tx_ring->tdt), i);
275 buffer_info->next_to_watch = i;
277 if (++i == tx_ring->count) i = 0;
279 /* Reply packet */
280 request->ios2_Req.io_Error = error;
281 request->ios2_WireError = wire_error;
282 Disable();
283 Remove((APTR)request);
284 Enable();
285 ReplyMsg((APTR)request);
287 /* Update statistics */
288 if(error == 0)
290 tracker = FindTypeStats(LIBBASE, unit, &unit->e1ku_type_trackers, request->ios2_PacketType);
292 if(tracker != NULL)
294 tracker->stats.PacketsSent++;
295 tracker->stats.BytesSent += packet_size;
300 tx_ring->next_to_use = i;
302 AROS_USERFUNC_EXIT
306 * Watchdog Interupt
308 static void e1000func_WatchdogHandler(HIDDT_IRQ_Handler *irq, HIDDT_IRQ_HwInfo *irq_hwi)
310 struct e1000Unit *unit = (struct e1000Unit *) irq->h_Data;
311 struct Device *TimerBase = unit->e1ku_TimerSlowReq->tr_node.io_Device;
312 struct timeval time;
314 GetSysTime(&time);
315 //D(bug("[%s]: ## e1000func_WatchdogHandler()\n", unit->e1ku_name));
318 * If timeout timer is expected, and time elapsed - regenerate the
319 * interrupt handler
321 if (unit->e1ku_toutNEED && (CmpTime(&time, &unit->e1ku_toutPOLL ) < 0))
323 unit->e1ku_toutNEED = FALSE;
324 //Cause(&unit->e1ku_tx_end_int);
329 * The interrupt handler - schedules code execution to proper handlers depending
330 * on the message from e1000.
332 * NOTE.
334 * Don't be surprised - this driver used to restart itself several times, in
335 * order to handle events which occur when the driver was handling previous
336 * events. It reduces the latency and amount of dropped packets. Additionally,
337 * this interrupt may put itself into deep sleep (or just quit) and restarts
338 * after certain amount of time (POLL_WAIT).
340 static void e1000func_IntHandler(HIDDT_IRQ_Handler *irq, HIDDT_IRQ_HwInfo *irq_hwi)
342 struct e1000Unit *unit = (struct e1000Unit *) irq->h_Data;
343 struct Device *TimerBase = unit->e1ku_TimerSlowReq->tr_node.io_Device;
344 struct timeval time;
345 int rx_cleaned, tx_cleaned, i, j;
347 ULONG icr = E1000_READ_REG((struct e1000_hw *)unit->e1ku_Private00, E1000_ICR);
349 D(bug("[%s]: e1000func_IntHandler(status %x): ", unit->e1ku_name, icr));
351 if (!icr)
353 D(bug("Skipping\n"));
354 return; /* Not our interrupt */
357 D(bug("Processing ..\n"));
358 GetSysTime(&time);
359 if (((struct e1000_hw *)unit->e1ku_Private00)->mac.type == e1000_82547 || ((struct e1000_hw *)unit->e1ku_Private00)->mac.type == e1000_82547_rev_2)
360 E1000_WRITE_REG((struct e1000_hw *)unit->e1ku_Private00, E1000_IMC, ~0);
362 // adapter->total_tx_bytes = 0;
363 // adapter->total_rx_bytes = 0;
364 // adapter->total_tx_packets = 0;
365 // adapter->total_rx_packets = 0;
367 for (i = 0; i < E1000_MAX_INTR; i++) {
368 rx_cleaned = 0;
369 for (j = 0; j < unit->e1ku_rxRing_QueueSize; j++)
370 rx_cleaned |= e1000func_clean_rx_irq(unit, &unit->e1ku_rxRing[j]);
372 tx_cleaned = 0;
373 for (j = 0 ; j < unit->e1ku_txRing_QueueSize ; j++)
374 tx_cleaned |= e1000func_clean_tx_irq(unit, &unit->e1ku_txRing[j]);
376 if (!rx_cleaned && !tx_cleaned)
377 break;
380 // if (adapter->itr_setting & 3)
381 // e1000_set_itr(adapter);
383 if (((struct e1000_hw *)unit->e1ku_Private00)->mac.type == e1000_82547 || ((struct e1000_hw *)unit->e1ku_Private00)->mac.type == e1000_82547_rev_2)
384 e1000func_irq_enable(unit);
386 return;
389 VOID CopyPacket(struct e1000Base *e1KBase, struct e1000Unit *unit,
390 struct IOSana2Req *request, UWORD packet_size, UWORD packet_type,
391 struct eth_frame *buffer)
393 struct Opener *opener;
394 BOOL filtered = FALSE;
395 UBYTE *ptr;
397 D(bug("[%s]: CopyPacket(packet @ %x, len = %d)\n", unit->e1ku_name, buffer, packet_size));
399 /* Set multicast and broadcast flags */
401 request->ios2_Req.io_Flags &= ~(SANA2IOF_BCAST | SANA2IOF_MCAST);
402 if((*((ULONG *)(buffer->eth_packet_dest)) == 0xffffffff) &&
403 (*((UWORD *)(buffer->eth_packet_dest + 4)) == 0xffff))
405 request->ios2_Req.io_Flags |= SANA2IOF_BCAST;
406 D(bug("[%s]: CopyPacket: BROADCAST Flag set\n", unit->e1ku_name));
408 else if((buffer->eth_packet_dest[0] & 0x1) != 0)
410 request->ios2_Req.io_Flags |= SANA2IOF_MCAST;
411 D(bug("[%s]: CopyPacket: MULTICAST Flag set\n", unit->e1ku_name));
414 /* Set source and destination addresses and packet type */
415 CopyMem(buffer->eth_packet_source, request->ios2_SrcAddr, ETH_ADDRESSSIZE);
416 CopyMem(buffer->eth_packet_dest, request->ios2_DstAddr, ETH_ADDRESSSIZE);
417 request->ios2_PacketType = packet_type;
419 /* Adjust for cooked packet request */
421 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
423 packet_size -= ETH_PACKET_DATA;
424 ptr = (UBYTE*)&buffer->eth_packet_data[0];
426 else
428 ptr = (UBYTE*)buffer;
431 request->ios2_DataLength = packet_size;
433 D(bug("[%s]: CopyPacket: packet @ %x (%d bytes)\n", unit->e1ku_name, ptr, packet_size));
435 /* Filter packet */
437 opener = request->ios2_BufferManagement;
438 if((request->ios2_Req.io_Command == CMD_READ) &&
439 (opener->filter_hook != NULL))
440 if(!CallHookPkt(opener->filter_hook, request, ptr))
442 D(bug("[%s]: CopyPacket: packet filtered\n", unit->e1ku_name));
443 filtered = TRUE;
446 if(!filtered)
448 /* Copy packet into opener's buffer and reply packet */
449 D(bug("[%s]: CopyPacket: opener recieve packet .. ", unit->e1ku_name));
450 if(!opener->rx_function(request->ios2_Data, ptr, packet_size))
452 D(bug("ERROR occured!!\n"));
453 request->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
454 request->ios2_WireError = S2WERR_BUFF_ERROR;
455 ReportEvents(LIBBASE, unit, S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF | S2EVENT_RX);
457 else
459 D(bug("SUCCESS!!\n"));
461 Disable();
462 Remove((APTR)request);
463 Enable();
464 ReplyMsg((APTR)request);
465 D(bug("[%s]: CopyPacket: opener notified.\n", unit->e1ku_name));
469 BOOL AddressFilter(struct e1000Base *e1KBase, struct e1000Unit *unit, UBYTE *address)
471 struct AddressRange *range, *tail;
472 BOOL accept = TRUE;
473 ULONG address_left;
474 UWORD address_right;
476 /* Check whether address is unicast/broadcast or multicast */
478 address_left = AROS_BE2LONG(*((ULONG *)address));
479 address_right = AROS_BE2WORD(*((UWORD *)(address + 4)));
481 if((address_left & 0x01000000) != 0 &&
482 !(address_left == 0xffffffff && address_right == 0xffff))
484 /* Check if this multicast address is wanted */
486 range = (APTR)unit->e1ku_multicast_ranges.mlh_Head;
487 tail = (APTR)&unit->e1ku_multicast_ranges.mlh_Tail;
488 accept = FALSE;
490 while((range != tail) && !accept)
492 if((address_left > range->lower_bound_left ||
493 (address_left == range->lower_bound_left &&
494 address_right >= range->lower_bound_right)) &&
495 (address_left < range->upper_bound_left ||
496 (address_left == range->upper_bound_left &&
497 address_right <= range->upper_bound_right)))
498 accept = TRUE;
499 range = (APTR)range->node.mln_Succ;
502 if(!accept)
503 unit->e1ku_special_stats[S2SS_ETHERNET_BADMULTICAST & 0xffff]++;
505 return accept;
509 * Unit process
511 AROS_UFH3(void, e1000func_Schedular,
512 AROS_UFHA(STRPTR, argPtr, A0),
513 AROS_UFHA(ULONG, argSize, D0),
514 AROS_UFHA(struct ExecBase *, SysBase, A6))
516 AROS_USERFUNC_INIT
518 struct e1000Startup *sm_UD = FindTask(NULL)->tc_UserData;
519 struct e1000Unit *unit = sm_UD->e1ksm_Unit;
521 LIBBASETYPEPTR LIBBASE = unit->e1ku_device;
522 APTR BattClockBase;
523 struct MsgPort *reply_port, *input;
525 D(bug("[%s] e1000func_Schedular()\n", unit->e1ku_name));
526 D(bug("[%s] e1000func_Schedular: Setting device up\n", unit->e1ku_name));
528 reply_port = CreateMsgPort();
529 input = CreateMsgPort();
531 unit->e1ku_input_port = input;
533 /* Randomize the generator with current time */
534 BattClockBase = OpenResource("battclock.resource");
535 srandom(ReadBattClock());
537 unit->e1ku_TimerSlowPort = CreateMsgPort();
539 if (unit->e1ku_TimerSlowPort)
541 unit->e1ku_TimerSlowReq = (struct timerequest *)
542 CreateIORequest((struct MsgPort *)unit->e1ku_TimerSlowPort, sizeof(struct timerequest));
544 if (unit->e1ku_TimerSlowReq)
546 if (!OpenDevice("timer.device", UNIT_VBLANK,
547 (struct IORequest *)unit->e1ku_TimerSlowReq, 0))
549 struct Message *msg = AllocVec(sizeof(struct Message), MEMF_PUBLIC|MEMF_CLEAR);
550 ULONG sigset;
552 D(bug("[%s] e1000func_Schedular: Got VBLANK unit of timer.device\n", unit->e1ku_name));
554 e1000func_reset(unit);
556 msg->mn_ReplyPort = reply_port;
557 msg->mn_Length = sizeof(struct Message);
559 D(bug("[%s] e1000func_Schedular: Setup complete. Sending handshake\n", unit->e1ku_name));
560 PutMsg(sm_UD->e1ksm_SyncPort, msg);
561 WaitPort(reply_port);
562 GetMsg(reply_port);
564 FreeVec(msg);
566 D(bug("[%s] e1000func_Schedular: entering forever loop ... \n", unit->e1ku_name));
568 unit->e1ku_signal_0 = AllocSignal(-1);
569 unit->e1ku_signal_1 = AllocSignal(-1);
570 unit->e1ku_signal_2 = AllocSignal(-1);
571 unit->e1ku_signal_3 = AllocSignal(-1);
573 sigset = 1 << input->mp_SigBit |
574 1 << unit->e1ku_signal_0 |
575 1 << unit->e1ku_signal_1 |
576 1 << unit->e1ku_signal_2 |
577 1 << unit->e1ku_signal_3;
578 for(;;)
580 ULONG recvd = Wait(sigset);
581 if (recvd & unit->e1ku_signal_0)
584 * Shutdown process. Driver should close everything
585 * already and waits for our process to complete. Free
586 * memory allocared here and kindly return.
588 // unit->deinitialize(unit);
589 CloseDevice((struct IORequest *)unit->e1ku_TimerSlowReq);
590 DeleteIORequest((struct IORequest *)unit->e1ku_TimerSlowReq);
591 DeleteMsgPort(unit->e1ku_TimerSlowPort);
592 DeleteMsgPort(input);
593 DeleteMsgPort(reply_port);
595 D(bug("[%s] e1000func_Schedular: Process shutdown.\n", unit->e1ku_name));
596 return;
598 else if (recvd & (1 << input->mp_SigBit))
600 struct IOSana2Req *io;
602 /* Handle incoming transactions */
603 while ((io = (struct IOSana2Req *)GetMsg(input))!= NULL)
605 D(bug("[%s] e1000func_Schedular: Handle incomming transaction.\n", unit->e1ku_name));
606 ObtainSemaphore(&unit->e1ku_unit_lock);
607 handle_request(LIBBASE, io);
610 else
612 D(bug("[%s] e1000func_Schedular: Handle incomming signal.\n", unit->e1ku_name));
613 /* Handle incoming signals */
620 AROS_USERFUNC_EXIT
624 * Create new e1000 ethernet device unit
626 #warning "TODO: Handle cleanup on failure in CreateUnit more elegantly"
627 struct e1000Unit *CreateUnit(struct e1000Base *e1KBase, OOP_Object *pciDevice)
629 struct e1000Unit *unit;
630 // UWORD eeprom_data = 0;
631 // UWORD eeprom_apme_mask = E1000_EEPROM_APME;
632 BOOL success = TRUE;
633 int i;
635 D(bug("[e1000] CreateUnit()\n"));
637 if ((unit = AllocMem(sizeof(struct e1000Unit), MEMF_PUBLIC | MEMF_CLEAR)) != NULL)
639 IPTR DeviceID,
640 RevisionID,
641 BaseAddr,
642 BaseType,
643 BaseLen,
644 IOBase = (IPTR)NULL,
645 Flash_Base = (IPTR)NULL,
646 MMIO_Base = (IPTR)NULL,
647 Flash_Size = 0,
648 MMIO_Size = 0;
649 OOP_Object *driver;
651 unit->e1ku_UnitNum = e1KBase->e1kb_UnitCount++;
653 unit->e1ku_Sana2Info.HardwareType = S2WireType_Ethernet;
654 unit->e1ku_Sana2Info.MTU = ETH_MTU;
655 unit->e1ku_Sana2Info.AddrFieldSize = 8 * ETH_ADDRESSSIZE;
657 if ((unit->e1ku_Private00 = (IPTR)AllocMem(sizeof(struct e1000_hw), MEMF_PUBLIC | MEMF_CLEAR)) == (IPTR)NULL)
659 FreeMem(unit, sizeof(struct e1000Unit));
660 return (IPTR)NULL;
663 if ((unit->e1ku_hw_stats = (struct e1000_hw_stats *)AllocMem(sizeof(struct e1000_hw_stats), MEMF_PUBLIC | MEMF_CLEAR)) == (IPTR)NULL)
665 FreeMem(unit->e1ku_Private00, sizeof(struct e1000_hw));
666 FreeMem(unit, sizeof(struct e1000Unit));
667 return (IPTR)NULL;
670 ((struct e1000_hw *)unit->e1ku_Private00)->back = unit;
672 if ((unit->e1ku_name = AllocVec(6 + (unit->e1ku_UnitNum/10) + 2, MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
674 FreeMem(unit->e1ku_hw_stats, sizeof(struct e1000_hw_stats));
675 FreeMem(unit->e1ku_Private00, sizeof(struct e1000_hw));
676 FreeMem(unit, sizeof(struct e1000Unit));
677 return (IPTR)NULL;
680 sprintf((char *)unit->e1ku_name, "e1000.%d", unit->e1ku_UnitNum);
682 OOP_GetAttr(pciDevice, aHidd_PCIDevice_ProductID, &DeviceID);
683 OOP_GetAttr(pciDevice, aHidd_PCIDevice_RevisionID, &RevisionID);
684 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Driver, (APTR)&driver);
686 unit->e1ku_device = e1KBase;
687 ((struct e1000_hw *)unit->e1ku_Private00)->device_id = DeviceID;
688 ((struct e1000_hw *)unit->e1ku_Private00)->revision_id = RevisionID;
690 unit->e1ku_mtu = unit->e1ku_Sana2Info.MTU;
691 unit->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
692 unit->e1ku_frame_max = unit->e1ku_mtu + ETH_HEADERSIZE + ETH_CRCSIZE;
693 unit->e1ku_frame_min = 60 + ETH_CRCSIZE;
695 unit->e1ku_PCIDevice = pciDevice;
696 unit->e1ku_PCIDriver = driver;
698 InitSemaphore(&unit->e1ku_unit_lock);
699 NEWLIST(&unit->e1ku_Openers);
700 NEWLIST(&unit->e1ku_multicast_ranges);
701 NEWLIST(&unit->e1ku_type_trackers);
703 OOP_GetAttr(pciDevice, aHidd_PCIDevice_INTLine, &unit->e1ku_IRQ);
704 D(bug("[%s] CreateUnit: Device IRQ : %d\n", unit->e1ku_name, unit->e1ku_IRQ));
706 for (i = 1; i <= 5; i++)
708 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Base0 + (i * 3), &BaseAddr);
709 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Type0 + (i * 3), &BaseType);
710 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Size0 + (i * 3), &BaseLen);
711 if ((BaseAddr != (IPTR)NULL) && (BaseLen > 0))
713 if (BaseType & ADDRF_IO)
715 IOBase = BaseAddr;
716 D(bug("[%s] CreateUnit: Device IO @ %p [%d bytes]\n", unit->e1ku_name, IOBase, BaseLen));
718 else
720 Flash_Base = BaseAddr;
721 Flash_Size = BaseLen;
722 D(bug("[%s] CreateUnit: Device Flash @ %p [%d bytes]\n", unit->e1ku_name, Flash_Base, Flash_Size));
727 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Base0, &MMIO_Base);
728 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Size0, &MMIO_Size);
729 D(bug("[%s] CreateUnit: Device MMIO @ %p\n", unit->e1ku_name, MMIO_Base));
731 ((struct e1000_hw *)unit->e1ku_Private00)->io_base = (unsigned long)IOBase;
732 ((struct e1000_hw *)unit->e1ku_Private00)->hw_addr = (UBYTE *)HIDD_PCIDriver_MapPCI(driver, (APTR)MMIO_Base, MMIO_Size);
733 unit->e1ku_MMIOSize = MMIO_Size;
735 D(bug("[%s] CreateUnit: Mapped MMIO @ %p [%d bytes]\n", unit->e1ku_name, ((struct e1000_hw *)unit->e1ku_Private00)->hw_addr, unit->e1ku_MMIOSize));
737 ((struct e1000_hw *)unit->e1ku_Private00)->flash_address = (UBYTE *)HIDD_PCIDriver_MapPCI(driver, (APTR)Flash_Base, Flash_Size);
738 unit->e1ku_FlashSize = Flash_Size;
740 D(bug("[%s] CreateUnit: Mapped Flash Memory @ %p [%d bytes]\n", unit->e1ku_name, ((struct e1000_hw *)unit->e1ku_Private00)->flash_address, unit->e1ku_FlashSize));
742 if ((((struct e1000_hw *)unit->e1ku_Private00)->io_base) && (((struct e1000_hw *)unit->e1ku_Private00)->hw_addr))
744 struct TagItem attrs[] = {
745 { aHidd_PCIDevice_isIO, TRUE },
746 { aHidd_PCIDevice_isMEM, TRUE },
747 { aHidd_PCIDevice_isMaster, TRUE },
748 { TAG_DONE, 0 },
750 OOP_SetAttrs(pciDevice, (struct TagItem *)&attrs);
752 unit->e1ku_DelayPort.mp_SigBit = SIGB_SINGLE;
753 unit->e1ku_DelayPort.mp_Flags = PA_SIGNAL;
754 unit->e1ku_DelayPort.mp_SigTask = FindTask(NULL);
755 unit->e1ku_DelayPort.mp_Node.ln_Type = NT_MSGPORT;
756 NEWLIST(&unit->e1ku_DelayPort.mp_MsgList);
758 unit->e1ku_DelayReq.tr_node.io_Message.mn_ReplyPort = &unit->e1ku_DelayPort;
759 unit->e1ku_DelayReq.tr_node.io_Message.mn_Length = sizeof(struct timerequest);
761 OpenDevice((STRPTR)"timer.device", UNIT_MICROHZ, (struct IORequest *)&unit->e1ku_DelayReq, 0);
763 /* Call e1000_api.c->e1000_setup_init_funcs */
764 if (e1000_setup_init_funcs((struct e1000_hw *)unit->e1ku_Private00, FALSE) != E1000_SUCCESS)
766 /* Should never have loaded on this device */
767 D(bug("[%s] CreateUnit: Called on unsupported NIC type!!\n", unit->e1ku_name));
768 e1KBase->e1kb_UnitCount = unit->e1ku_UnitNum;
769 FreeVec(unit->e1ku_name);
770 FreeMem(unit->e1ku_Private00, sizeof(struct e1000_hw));
771 FreeMem(unit, sizeof(struct e1000Unit));
772 return NULL;
775 D(bug("[%s] CreateUnit: Initialised Intel NIC functions..\n", unit->e1ku_name));
777 unit->e1ku_txRing_QueueSize = 1;
778 if ((unit->e1ku_txRing = AllocMem(sizeof(struct e1000_tx_ring) * unit->e1ku_txRing_QueueSize, MEMF_PUBLIC|MEMF_CLEAR)) == NULL)
780 #warning "TODO: Handle Tx Queue allocation failure more elegantly!"
781 D(bug("[%s] CreateUnit: Failed to Allocate Tx Ring Queue!!!\n", unit->e1ku_name));
782 return NULL;
784 D(bug("[%s] CreateUnit: Queue 0 TxRing @ %p\n", unit->e1ku_name, unit->e1ku_txRing));
786 unit->e1ku_rxRing_QueueSize = 1;
787 if ((unit->e1ku_rxRing = AllocMem(sizeof(struct e1000_rx_ring) * unit->e1ku_rxRing_QueueSize, MEMF_PUBLIC|MEMF_CLEAR)) == NULL)
789 #warning "TODO: Handle Rx Queue allocation failure more elegantly!"
790 D(bug("[%s] CreateUnit: Failed to Allocate Rx Ring Queue!!!\n", unit->e1ku_name));
791 return NULL;
793 D(bug("[%s] CreateUnit: Queue 0 RxRing @ %p\n", unit->e1ku_name, unit->e1ku_rxRing));
795 e1000func_irq_disable(unit);
796 D(bug("[%s] CreateUnit: e1000 IRQ disabled\n", unit->e1ku_name));
798 if (e1000_init_mac_params((struct e1000_hw *)unit->e1ku_Private00) != E1000_SUCCESS)
800 D(bug("[%s] CreateUnit: Failed to init mac params\n", unit->e1ku_name));
802 D(bug("[%s] CreateUnit: MAC Params Initialised\n", unit->e1ku_name));
804 if (e1000_init_nvm_params((struct e1000_hw *)unit->e1ku_Private00) != E1000_SUCCESS)
806 D(bug("[%s] CreateUnit: Failed to init nvm params\n", unit->e1ku_name));
808 D(bug("[%s] CreateUnit: NVM Params Initialised\n", unit->e1ku_name));
810 if (e1000_init_phy_params((struct e1000_hw *)unit->e1ku_Private00) != E1000_SUCCESS)
812 D(bug("[%s] CreateUnit: Failed to init phy params\n", unit->e1ku_name));
814 D(bug("[%s] CreateUnit: PHY Params Initialised\n", unit->e1ku_name));
816 e1000_get_bus_info((struct e1000_hw *)unit->e1ku_Private00);
818 D(bug("[%s] CreateUnit: Retrieved Bus information..\n", unit->e1ku_name));
820 e1000_init_script_state_82541((struct e1000_hw *)unit->e1ku_Private00, TRUE);
821 e1000_set_tbi_compatibility_82543((struct e1000_hw *)unit->e1ku_Private00, TRUE);
823 D(bug("[%s] CreateUnit: 82541/82543 Setup complete\n", unit->e1ku_name));
825 ((struct e1000_hw *)unit->e1ku_Private00)->phy.autoneg_wait_to_complete = FALSE;
826 ((struct e1000_hw *)unit->e1ku_Private00)->mac.adaptive_ifs = TRUE;
828 /* Copper options */
830 if (((struct e1000_hw *)unit->e1ku_Private00)->phy.media_type == e1000_media_type_copper)
832 ((struct e1000_hw *)unit->e1ku_Private00)->phy.mdix = AUTO_ALL_MODES;
833 ((struct e1000_hw *)unit->e1ku_Private00)->phy.disable_polarity_correction = FALSE;
834 ((struct e1000_hw *)unit->e1ku_Private00)->phy.ms_type = E1000_MASTER_SLAVE;
837 if (e1000_check_reset_block((struct e1000_hw *)unit->e1ku_Private00))
839 D(bug("[%s] CreateUnit: PHY reset is blocked due to SOL/IDER session.\n", unit->e1ku_name));
842 /* Hardware features, flags and workarounds */
843 if (((struct e1000_hw *)unit->e1ku_Private00)->mac.type >= e1000_82540) {
844 unit->e1ku_hwflags |= E1000_FLAG_HAS_SMBUS;
845 unit->e1ku_hwflags |= E1000_FLAG_HAS_INTR_MODERATION;
848 if (((struct e1000_hw *)unit->e1ku_Private00)->mac.type == e1000_82543)
849 unit->e1ku_hwflags |= E1000_FLAG_BAD_TX_CARRIER_STATS_FD;
851 e1000_reset_hw((struct e1000_hw *)unit->e1ku_Private00);
852 D(bug("[%s] CreateUnit: e1000 hardware reset\n", unit->e1ku_name));
854 if (e1000_validate_nvm_checksum((struct e1000_hw *)unit->e1ku_Private00) < 0) {
855 D(bug("[%s] CreateUnit: Warning: The NVM Checksum Is Not Valid!\n", unit->e1ku_name));
856 return NULL;
858 else
860 D(bug("[%s] CreateUnit: NVM Checksum validated succesfully\n", unit->e1ku_name));
863 /* copy the MAC address out of the NVM */
865 if (e1000_read_mac_addr((struct e1000_hw *)unit->e1ku_Private00))
867 D(bug("[%s] CreateUnit: NVM Read Error\n", unit->e1ku_name));
869 else
871 D(bug("[%s] CreateUnit: MAC Address Read\n", unit->e1ku_name));
873 memcpy(unit->e1ku_org_addr, ((struct e1000_hw *)unit->e1ku_Private00)->mac.addr, ETH_ADDRESSSIZE);
874 memcpy(unit->e1ku_dev_addr, unit->e1ku_org_addr, ETH_ADDRESSSIZE);
876 D(bug("[%s] CreateUnit: MAC Address %02x:%02x:%02x:%02x:%02x:%02x\n", unit->e1ku_name,
877 unit->e1ku_dev_addr[0], unit->e1ku_dev_addr[1], unit->e1ku_dev_addr[2],
878 unit->e1ku_dev_addr[3], unit->e1ku_dev_addr[4], unit->e1ku_dev_addr[5]));
881 D(bug("[%s] CreateUnit: (PCI%s:%s:%s)\n", unit->e1ku_name,
882 ((((struct e1000_hw *)unit->e1ku_Private00)->bus.type == e1000_bus_type_pcix) ? "-X" :
883 (((struct e1000_hw *)unit->e1ku_Private00)->bus.type == e1000_bus_type_pci_express ? " Express":"")),
884 ((((struct e1000_hw *)unit->e1ku_Private00)->bus.speed == e1000_bus_speed_2500) ? "2.5Gb/s" :
885 (((struct e1000_hw *)unit->e1ku_Private00)->bus.speed == e1000_bus_speed_133) ? "133MHz" :
886 (((struct e1000_hw *)unit->e1ku_Private00)->bus.speed == e1000_bus_speed_120) ? "120MHz" :
887 (((struct e1000_hw *)unit->e1ku_Private00)->bus.speed == e1000_bus_speed_100) ? "100MHz" :
888 (((struct e1000_hw *)unit->e1ku_Private00)->bus.speed == e1000_bus_speed_66) ? "66MHz" : "33MHz"),
889 ((((struct e1000_hw *)unit->e1ku_Private00)->bus.width == e1000_bus_width_64) ? "64-bit" :
890 (((struct e1000_hw *)unit->e1ku_Private00)->bus.width == e1000_bus_width_pcie_x4) ? "Width x4" :
891 (((struct e1000_hw *)unit->e1ku_Private00)->bus.width == e1000_bus_width_pcie_x1) ? "Width x1" :
892 "32-bit")));
895 unit->e1ku_irqhandler = AllocMem(sizeof(HIDDT_IRQ_Handler), MEMF_PUBLIC|MEMF_CLEAR);
896 unit->e1ku_touthandler = AllocMem(sizeof(HIDDT_IRQ_Handler), MEMF_PUBLIC|MEMF_CLEAR);
898 if (unit->e1ku_irqhandler && unit->e1ku_touthandler)
900 struct Message *msg;
902 unit->e1ku_irqhandler->h_Node.ln_Pri = 100;
903 unit->e1ku_irqhandler->h_Node.ln_Name = LIBBASE->e1kb_Device.dd_Library.lib_Node.ln_Name;
904 unit->e1ku_irqhandler->h_Code = e1000func_IntHandler;
905 unit->e1ku_irqhandler->h_Data = unit;
907 unit->e1ku_touthandler->h_Node.ln_Pri = 100;
908 unit->e1ku_touthandler->h_Node.ln_Name = LIBBASE->e1kb_Device.dd_Library.lib_Node.ln_Name;
909 unit->e1ku_touthandler->h_Code = e1000func_WatchdogHandler;
910 unit->e1ku_touthandler->h_Data = unit;
912 unit->e1ku_tx_int.is_Node.ln_Name = unit->e1ku_name;
913 unit->e1ku_tx_int.is_Code = e1000func_TX_Int;
914 unit->e1ku_tx_int.is_Data = unit;
916 for (i = 0; i < REQUEST_QUEUE_COUNT; i++)
918 struct MsgPort *port;
920 if ((port = AllocMem(sizeof(struct MsgPort), MEMF_PUBLIC | MEMF_CLEAR)) == NULL) success = FALSE;
922 if (success)
924 unit->e1ku_request_ports[i] = port;
925 NEWLIST(&port->mp_MsgList);
926 port->mp_Flags = PA_IGNORE;
927 port->mp_SigTask = &unit->e1ku_tx_int;
931 unit->e1ku_request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
933 if (success)
935 struct e1000Startup *sm_UD;
936 UBYTE tmpbuff[100];
938 if ((sm_UD = AllocMem(sizeof(struct e1000Startup), MEMF_PUBLIC | MEMF_CLEAR)) != NULL)
940 sprintf((char *)tmpbuff, e1000_TASK_NAME, unit->e1ku_name);
942 sm_UD->e1ksm_SyncPort = CreateMsgPort();
943 sm_UD->e1ksm_Unit = unit;
945 unit->e1ku_Process = CreateNewProcTags(
946 NP_Entry, (IPTR)e1000func_Schedular,
947 NP_Name, tmpbuff,
948 NP_Synchronous , FALSE,
949 NP_Priority, 0,
950 NP_UserData, (IPTR)sm_UD,
951 NP_StackSize, 140960,
952 TAG_DONE);
954 WaitPort(sm_UD->e1ksm_SyncPort);
955 msg = GetMsg(sm_UD->e1ksm_SyncPort);
956 ReplyMsg(msg);
957 DeleteMsgPort(sm_UD->e1ksm_SyncPort);
958 FreeMem(sm_UD, sizeof(struct e1000Startup));
960 D(bug("[%s] CreateUnit: Device Initialised. Unit %d @ %p\n", unit->e1ku_name, unit->e1ku_UnitNum, unit));
961 return unit;
966 else
968 if ((((struct e1000_hw *)unit->e1ku_Private00)->io_base) == (IPTR)NULL)
970 D(bug("[%s] CreateUnit: PANIC! Couldn't find IO area. Aborting\n", unit->e1ku_name));
973 if ((((struct e1000_hw *)unit->e1ku_Private00)->hw_addr) == (IPTR)NULL)
975 D(bug("[%s] CreateUnit: PANIC! Couldn't get MMIO area. Aborting\n", unit->e1ku_name));
979 DeleteUnit(e1KBase, unit);
980 return NULL;
984 * DeleteUnit - removes selected unit. Frees all resources and structures.
986 * The caller should be sure, that given unit is really ready to be freed.
989 void DeleteUnit(struct e1000Base *e1KBase, struct e1000Unit *unit)
991 int i;
992 if (unit)
994 if (unit->e1ku_Process)
996 Signal(&unit->e1ku_Process->pr_Task, unit->e1ku_signal_0);
999 for (i=0; i < REQUEST_QUEUE_COUNT; i++)
1001 if (unit->e1ku_request_ports[i] != NULL)
1002 FreeMem(unit->e1ku_request_ports[i], sizeof(struct MsgPort));
1004 unit->e1ku_request_ports[i] = NULL;
1007 if (unit->e1ku_irqhandler)
1009 FreeMem(unit->e1ku_irqhandler, sizeof(HIDDT_IRQ_Handler));
1012 if ((struct e1000_hw *)unit->e1ku_Private00)
1014 if (((struct e1000_hw *)unit->e1ku_Private00)->hw_addr)
1016 HIDD_PCIDriver_UnmapPCI(unit->e1ku_PCIDriver,
1017 (APTR)((struct e1000_hw *)unit->e1ku_Private00)->hw_addr,
1018 unit->e1ku_MMIOSize);
1020 FreeMem(unit->e1ku_Private00, sizeof(struct e1000_hw));
1023 if (unit->e1ku_name)
1024 FreeVec(unit->e1ku_name);
1026 FreeMem(unit, sizeof(struct e1000Unit));
1030 static struct AddressRange *FindMulticastRange(LIBBASETYPEPTR LIBBASE, struct e1000Unit *unit,
1031 ULONG lower_bound_left, UWORD lower_bound_right, ULONG upper_bound_left, UWORD upper_bound_right)
1033 struct AddressRange *range, *tail;
1034 BOOL found = FALSE;
1036 range = (APTR)unit->e1ku_multicast_ranges.mlh_Head;
1037 tail = (APTR)&unit->e1ku_multicast_ranges.mlh_Tail;
1039 while((range != tail) && !found)
1041 if((lower_bound_left == range->lower_bound_left) &&
1042 (lower_bound_right == range->lower_bound_right) &&
1043 (upper_bound_left == range->upper_bound_left) &&
1044 (upper_bound_right == range->upper_bound_right))
1045 found = TRUE;
1046 else
1047 range = (APTR)range->node.mln_Succ;
1050 if(!found)
1051 range = NULL;
1053 return range;
1056 BOOL AddMulticastRange(LIBBASETYPEPTR LIBBASE, struct e1000Unit *unit, const UBYTE *lower_bound,
1057 const UBYTE *upper_bound)
1059 struct AddressRange *range;
1060 ULONG lower_bound_left, upper_bound_left;
1061 UWORD lower_bound_right, upper_bound_right;
1063 lower_bound_left = AROS_BE2LONG(*((ULONG *)lower_bound));
1064 lower_bound_right = AROS_BE2WORD(*((UWORD *)(lower_bound + 4)));
1065 upper_bound_left = AROS_BE2LONG(*((ULONG *)upper_bound));
1066 upper_bound_right = AROS_BE2WORD(*((UWORD *)(upper_bound + 4)));
1068 range = FindMulticastRange(LIBBASE, unit, lower_bound_left, lower_bound_right,
1069 upper_bound_left, upper_bound_right);
1071 if(range != NULL)
1072 range->add_count++;
1073 else
1075 range = AllocMem(sizeof(struct AddressRange), MEMF_PUBLIC);
1076 if(range != NULL)
1078 range->lower_bound_left = lower_bound_left;
1079 range->lower_bound_right = lower_bound_right;
1080 range->upper_bound_left = upper_bound_left;
1081 range->upper_bound_right = upper_bound_right;
1082 range->add_count = 1;
1084 Disable();
1085 AddTail((APTR)&unit->e1ku_multicast_ranges, (APTR)range);
1086 Enable();
1088 if (unit->e1ku_range_count++ == 0)
1090 unit->e1ku_ifflags |= IFF_ALLMULTI;
1091 e1000func_set_multi(unit);
1096 return range != NULL;
1099 BOOL RemMulticastRange(LIBBASETYPEPTR LIBBASE, struct e1000Unit *unit, const UBYTE *lower_bound, const UBYTE *upper_bound)
1101 struct AddressRange *range;
1102 ULONG lower_bound_left, upper_bound_left;
1103 UWORD lower_bound_right, upper_bound_right;
1105 lower_bound_left = AROS_BE2LONG(*((ULONG *)lower_bound));
1106 lower_bound_right = AROS_BE2WORD(*((UWORD *)(lower_bound + 4)));
1107 upper_bound_left = AROS_BE2LONG(*((ULONG *)upper_bound));
1108 upper_bound_right = AROS_BE2WORD(*((UWORD *)(upper_bound + 4)));
1110 range = FindMulticastRange(LIBBASE, unit, lower_bound_left, lower_bound_right,
1111 upper_bound_left, upper_bound_right);
1113 if(range != NULL)
1115 if(--range->add_count == 0)
1117 Disable();
1118 Remove((APTR)range);
1119 Enable();
1120 FreeMem(range, sizeof(struct AddressRange));
1122 if (--unit->e1ku_range_count == 0)
1124 unit->e1ku_ifflags &= ~IFF_ALLMULTI;
1125 e1000func_set_multi(unit);
1129 return range != NULL;