grub2: bring back build of aros-side grub2 tools
[AROS.git] / workbench / devs / networks / e1000 / unit.c
blob151d58cc21e91c081937adfdd3d2a388ff749099
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/oop.h>
41 #include <proto/timer.h>
42 #include <proto/utility.h>
44 #include <stdlib.h>
45 #include <stdio.h>
47 #include "e1000_hw.h"
48 #include "e1000_api.h"
49 #include "e1000_defines.h"
50 #include "unit.h"
51 #include LC_LIBDEFS_FILE
54 * Report incoming events to all hyphotetical event receivers
56 VOID ReportEvents(struct e1000Base *e1KBase, struct e1000Unit *unit, ULONG events)
58 struct IOSana2Req *request, *tail, *next_request;
59 struct List *list;
61 list = &unit->e1ku_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 e1000Base *e1KBase, struct e1000Unit *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 e1000Unit *unit, UBYTE last_queue, BYTE error)
109 struct IORequest *request;
110 UBYTE i;
111 struct Opener *opener, *tail;
113 D(bug("[%s] unit.FlushUnit\n", unit->e1ku_name));
115 /* Abort queued operations */
117 for (i=0; i <= last_queue; i++)
119 while ((request = (APTR)GetMsg(unit->e1ku_request_ports[i])) != NULL)
121 request->io_Error = IOERR_ABORTED;
122 ReplyMsg((struct Message *)request);
126 opener = (APTR)unit->e1ku_Openers.mlh_Head;
127 tail = (APTR)&unit->e1ku_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;
143 * Interrupt generated by Cause() to push new packets into the NIC interface
145 static AROS_INTH1(e1000func_TX_Int, struct e1000Unit *, unit)
147 AROS_INTFUNC_INIT
149 struct e1000Base *e1KBase = unit->e1ku_device;
150 struct e1000_tx_ring *tx_ring = &unit->e1ku_txRing[0];
151 struct e1000_tx_desc *tx_desc = NULL;
152 struct e1000_buffer *buffer_info;
153 struct eth_frame *frame;
154 struct IOSana2Req *request;
155 struct Opener *opener;
156 struct MsgPort *port;
157 struct TypeStats *tracker;
158 int tx_flags = E1000_TX_FLAGS_IPV4;
159 unsigned int i;
160 ULONG txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
161 UWORD packet_size, data_size;
162 UBYTE *buffer, error;
163 ULONG wire_error=0;
164 BOOL proceed = FALSE;
166 D(bug("[%s]: ## e1000func_TX_Int()\n", unit->e1ku_name));
168 if (tx_flags & E1000_TX_FLAGS_TSO) {
169 txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D |
170 E1000_TXD_CMD_TSE;
171 txd_upper |= E1000_TXD_POPTS_TXSM << 8;
173 if (tx_flags & E1000_TX_FLAGS_IPV4)
174 txd_upper |= E1000_TXD_POPTS_IXSM << 8;
177 if (tx_flags & E1000_TX_FLAGS_CSUM) {
178 txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
179 txd_upper |= E1000_TXD_POPTS_TXSM << 8;
182 if (tx_flags & E1000_TX_FLAGS_VLAN) {
183 txd_lower |= E1000_TXD_CMD_VLE;
184 txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK);
187 i = tx_ring->next_to_use;
189 proceed = TRUE; /* Success by default */
190 port = unit->e1ku_request_ports[WRITE_QUEUE];
192 D(bug("[%s]: ## e1000func_TX_Int: nxt to use = %d, write queue port @ %p\n", unit->e1ku_name, i, port));
194 while(proceed && (!IsMsgPortEmpty(port)))
196 error = 0;
197 request = (APTR)port->mp_MsgList.lh_Head;
198 data_size = packet_size = request->ios2_DataLength;
200 opener = (APTR)request->ios2_BufferManagement;
202 buffer_info = &tx_ring->buffer_info[i];
204 if ((buffer_info->buffer = AllocMem(ETH_MAXPACKETSIZE, MEMF_PUBLIC|MEMF_CLEAR)) != NULL)
206 frame = buffer_info->buffer;
208 if ((buffer_info->dma = HIDD_PCIDriver_CPUtoPCI(unit->e1ku_PCIDriver, buffer_info->buffer)) == NULL)
210 D(bug("[%s]: e1000func_TX_Int: Failed to Map Tx DMA buffer\n", unit->e1ku_name));
212 else
214 D(bug("[%s]: e1000func_TX_Int: Tx DMA buffer %d @ %p\n", unit->e1ku_name, i, buffer_info->dma));
217 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
219 packet_size += ETH_PACKET_DATA;
220 CopyMem(request->ios2_DstAddr, frame->eth_packet_dest, ETH_ADDRESSSIZE);
221 CopyMem(unit->e1ku_dev_addr, frame->eth_packet_source, ETH_ADDRESSSIZE);
222 frame->eth_packet_type = AROS_WORD2BE(request->ios2_PacketType);
224 buffer = frame->eth_packet_data;
226 else
227 buffer = (UBYTE *)frame;
229 if (!opener->tx_function(buffer, request->ios2_Data, data_size))
231 error = S2ERR_NO_RESOURCES;
232 wire_error = S2WERR_BUFF_ERROR;
233 ReportEvents(LIBBASE, unit,
234 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF
235 | S2EVENT_TX);
238 /* Now the packet is already in TX buffer, update flags for NIC */
239 if (error == 0)
241 Disable();
242 D(bug("[%s]: e1000func_TX_Int: packet %d [type = %d] queued for transmission.\n", unit->e1ku_name, i, AROS_BE2WORD(frame->eth_packet_type)));
244 /* DEBUG? Dump frame if so */
245 #ifdef DEBUG
247 int j;
248 D(bug("[%s]: Tx Buffer %d Packet Dump -:", unit->e1ku_name, i));
249 for (j=0; j<64; j++) {
250 if ((j%16) == 0)
251 D(bug("\n[%s]: %03x:", unit->e1ku_name, j));
252 D(bug(" %02x", ((unsigned char*)frame)[j]));
254 D(bug("\n"));
256 #endif
257 Enable();
259 /* Set the ring details for the packet .. */
260 buffer_info->length = packet_size;
262 tx_desc = E1000_TX_DESC(tx_ring, i);
263 tx_desc->buffer_addr = (IPTR)buffer_info->dma;
264 tx_desc->lower.data = AROS_WORD2LE(txd_lower | buffer_info->length);
265 tx_desc->upper.data = AROS_WORD2LE(txd_upper);
266 tx_desc->lower.data |= AROS_WORD2LE(unit->txd_cmd);
267 MMIO_W32((APTR)(((struct e1000_hw *)unit->e1ku_Private00)->hw_addr + tx_ring->tdt), i);
271 buffer_info->next_to_watch = i;
273 if (++i == tx_ring->count) i = 0;
275 /* Reply packet */
276 request->ios2_Req.io_Error = error;
277 request->ios2_WireError = wire_error;
278 Disable();
279 Remove((APTR)request);
280 Enable();
281 ReplyMsg((APTR)request);
283 /* Update statistics */
284 if(error == 0)
286 tracker = FindTypeStats(LIBBASE, unit, &unit->e1ku_type_trackers, request->ios2_PacketType);
288 if(tracker != NULL)
290 tracker->stats.PacketsSent++;
291 tracker->stats.BytesSent += packet_size;
296 tx_ring->next_to_use = i;
298 return 0;
300 AROS_INTFUNC_EXIT
304 * Watchdog Interupt
306 AROS_INTH1(e1000func_WatchdogHandler,struct e1000Unit *,unit)
308 AROS_INTFUNC_INIT
310 struct Device *TimerBase = unit->e1ku_TimerSlowReq->tr_node.io_Device;
311 struct timeval time;
313 GetSysTime(&time);
314 //D(bug("[%s]: ## e1000func_WatchdogHandler()\n", unit->e1ku_name));
317 * If timeout timer is expected, and time elapsed - regenerate the
318 * interrupt handler
320 if (unit->e1ku_toutNEED && (CmpTime(&time, &unit->e1ku_toutPOLL ) < 0))
322 unit->e1ku_toutNEED = FALSE;
323 //Cause(&unit->e1ku_tx_end_int);
326 return FALSE;
328 AROS_INTFUNC_EXIT
332 * The interrupt handler - schedules code execution to proper handlers depending
333 * on the message from e1000.
335 * NOTE.
337 * Don't be surprised - this driver used to restart itself several times, in
338 * order to handle events which occur when the driver was handling previous
339 * events. It reduces the latency and amount of dropped packets. Additionally,
340 * this interrupt may put itself into deep sleep (or just quit) and restarts
341 * after certain amount of time (POLL_WAIT).
343 AROS_INTH1(e1000func_IntHandler,struct e1000Unit *,unit)
345 AROS_INTFUNC_INIT
347 struct Device *TimerBase = unit->e1ku_TimerSlowReq->tr_node.io_Device;
348 struct timeval time;
349 int rx_cleaned, tx_cleaned, i, j;
351 ULONG icr = E1000_READ_REG((struct e1000_hw *)unit->e1ku_Private00, E1000_ICR);
353 D(bug("[%s]: e1000func_IntHandler(status %x): ", unit->e1ku_name, icr));
355 if (!icr)
357 D(bug("Skipping\n"));
358 return FALSE; /* Not our interrupt */
361 D(bug("Processing ..\n"));
362 GetSysTime(&time);
363 if (((struct e1000_hw *)unit->e1ku_Private00)->mac.type == e1000_82547 || ((struct e1000_hw *)unit->e1ku_Private00)->mac.type == e1000_82547_rev_2)
364 E1000_WRITE_REG((struct e1000_hw *)unit->e1ku_Private00, E1000_IMC, ~0);
366 // adapter->total_tx_bytes = 0;
367 // adapter->total_rx_bytes = 0;
368 // adapter->total_tx_packets = 0;
369 // adapter->total_rx_packets = 0;
371 for (i = 0; i < E1000_MAX_INTR; i++) {
372 rx_cleaned = 0;
373 for (j = 0; j < unit->e1ku_rxRing_QueueSize; j++)
374 rx_cleaned |= e1000func_clean_rx_irq(unit, &unit->e1ku_rxRing[j]);
376 tx_cleaned = 0;
377 for (j = 0 ; j < unit->e1ku_txRing_QueueSize ; j++)
378 tx_cleaned |= e1000func_clean_tx_irq(unit, &unit->e1ku_txRing[j]);
380 if (!rx_cleaned && !tx_cleaned)
381 break;
384 // if (adapter->itr_setting & 3)
385 // e1000_set_itr(adapter);
387 if (((struct e1000_hw *)unit->e1ku_Private00)->mac.type == e1000_82547 || ((struct e1000_hw *)unit->e1ku_Private00)->mac.type == e1000_82547_rev_2)
388 e1000func_irq_enable(unit);
390 return 0;
392 AROS_INTFUNC_EXIT
395 VOID CopyPacket(struct e1000Base *e1KBase, struct e1000Unit *unit,
396 struct IOSana2Req *request, UWORD packet_size, UWORD packet_type,
397 struct eth_frame *buffer)
399 struct Opener *opener;
400 BOOL filtered = FALSE;
401 UBYTE *ptr;
402 const UBYTE broadcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
404 D(bug("[%s]: CopyPacket(packet @ %x, len = %d)\n", unit->e1ku_name, buffer, packet_size));
406 /* Set multicast and broadcast flags */
408 request->ios2_Req.io_Flags &= ~(SANA2IOF_BCAST | SANA2IOF_MCAST);
409 if(memcmp(buffer->eth_packet_dest, broadcast, ETH_ADDRESSSIZE) == 0)
411 request->ios2_Req.io_Flags |= SANA2IOF_BCAST;
412 D(bug("[%s]: CopyPacket: BROADCAST Flag set\n", unit->e1ku_name));
414 else if((buffer->eth_packet_dest[0] & 0x1) != 0)
416 request->ios2_Req.io_Flags |= SANA2IOF_MCAST;
417 D(bug("[%s]: CopyPacket: MULTICAST Flag set\n", unit->e1ku_name));
420 /* Set source and destination addresses and packet type */
421 CopyMem(buffer->eth_packet_source, request->ios2_SrcAddr, ETH_ADDRESSSIZE);
422 CopyMem(buffer->eth_packet_dest, request->ios2_DstAddr, ETH_ADDRESSSIZE);
423 request->ios2_PacketType = packet_type;
425 /* Adjust for cooked packet request */
427 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
429 packet_size -= ETH_PACKET_DATA;
430 ptr = (UBYTE*)&buffer->eth_packet_data[0];
432 else
434 ptr = (UBYTE*)buffer;
437 request->ios2_DataLength = packet_size;
439 D(bug("[%s]: CopyPacket: packet @ %x (%d bytes)\n", unit->e1ku_name, ptr, packet_size));
441 /* Filter packet */
443 opener = request->ios2_BufferManagement;
444 if((request->ios2_Req.io_Command == CMD_READ) &&
445 (opener->filter_hook != NULL))
446 if(!CallHookPkt(opener->filter_hook, request, ptr))
448 D(bug("[%s]: CopyPacket: packet filtered\n", unit->e1ku_name));
449 filtered = TRUE;
452 if(!filtered)
454 /* Copy packet into opener's buffer and reply packet */
455 D(bug("[%s]: CopyPacket: opener recieve packet .. ", unit->e1ku_name));
456 if(!opener->rx_function(request->ios2_Data, ptr, packet_size))
458 D(bug("ERROR occured!!\n"));
459 request->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
460 request->ios2_WireError = S2WERR_BUFF_ERROR;
461 ReportEvents(LIBBASE, unit, S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF | S2EVENT_RX);
463 else
465 D(bug("SUCCESS!!\n"));
467 Disable();
468 Remove((APTR)request);
469 Enable();
470 ReplyMsg((APTR)request);
471 D(bug("[%s]: CopyPacket: opener notified.\n", unit->e1ku_name));
475 BOOL AddressFilter(struct e1000Base *e1KBase, struct e1000Unit *unit, UBYTE *address)
477 struct AddressRange *range, *tail;
478 BOOL accept = TRUE;
479 const UBYTE broadcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
481 /* Check whether address is unicast/broadcast or multicast */
483 if((address[0] & 0x01) != 0 && memcmp(address, broadcast, ETH_ADDRESSSIZE) != 0)
485 /* Check if this multicast address is wanted */
487 range = (APTR)unit->e1ku_multicast_ranges.mlh_Head;
488 tail = (APTR)&unit->e1ku_multicast_ranges.mlh_Tail;
489 accept = FALSE;
491 while((range != tail) && !accept)
493 if ((memcmp(address, range->lower_bound, ETH_ADDRESSSIZE) >= 0) &&
494 (memcmp(address, range->upper_bound, ETH_ADDRESSSIZE) <= 0))
495 accept = TRUE;
496 range = (APTR)range->node.mln_Succ;
499 if(!accept)
500 unit->e1ku_special_stats[S2SS_ETHERNET_BADMULTICAST & 0xffff]++;
502 return accept;
506 * Unit process
508 AROS_UFH3(void, e1000func_Schedular,
509 AROS_UFHA(STRPTR, argPtr, A0),
510 AROS_UFHA(ULONG, argSize, D0),
511 AROS_UFHA(struct ExecBase *, SysBase, A6))
513 AROS_USERFUNC_INIT
515 struct e1000Startup *sm_UD = FindTask(NULL)->tc_UserData;
516 struct e1000Unit *unit = sm_UD->e1ksm_Unit;
518 LIBBASETYPEPTR LIBBASE = unit->e1ku_device;
519 struct MsgPort *reply_port, *input;
521 D(bug("[%s] e1000func_Schedular()\n", unit->e1ku_name));
522 D(bug("[%s] e1000func_Schedular: Setting device up\n", unit->e1ku_name));
524 reply_port = CreateMsgPort();
525 input = CreateMsgPort();
527 unit->e1ku_input_port = input;
529 unit->e1ku_TimerSlowPort = CreateMsgPort();
531 if (unit->e1ku_TimerSlowPort)
533 unit->e1ku_TimerSlowReq = (struct timerequest *)
534 CreateIORequest((struct MsgPort *)unit->e1ku_TimerSlowPort, sizeof(struct timerequest));
536 if (unit->e1ku_TimerSlowReq)
538 if (!OpenDevice("timer.device", UNIT_VBLANK,
539 (struct IORequest *)unit->e1ku_TimerSlowReq, 0))
541 struct Message *msg = AllocVec(sizeof(struct Message), MEMF_PUBLIC|MEMF_CLEAR);
542 ULONG sigset;
544 D(bug("[%s] e1000func_Schedular: Got VBLANK unit of timer.device\n", unit->e1ku_name));
546 e1000func_reset(unit);
548 msg->mn_ReplyPort = reply_port;
549 msg->mn_Length = sizeof(struct Message);
551 D(bug("[%s] e1000func_Schedular: Setup complete. Sending handshake\n", unit->e1ku_name));
552 PutMsg(sm_UD->e1ksm_SyncPort, msg);
553 WaitPort(reply_port);
554 GetMsg(reply_port);
556 FreeVec(msg);
558 D(bug("[%s] e1000func_Schedular: entering forever loop ... \n", unit->e1ku_name));
560 unit->e1ku_signal_0 = AllocSignal(-1);
561 unit->e1ku_signal_1 = AllocSignal(-1);
562 unit->e1ku_signal_2 = AllocSignal(-1);
563 unit->e1ku_signal_3 = AllocSignal(-1);
565 sigset = 1 << input->mp_SigBit |
566 1 << unit->e1ku_signal_0 |
567 1 << unit->e1ku_signal_1 |
568 1 << unit->e1ku_signal_2 |
569 1 << unit->e1ku_signal_3;
570 for(;;)
572 ULONG recvd = Wait(sigset);
573 if (recvd & unit->e1ku_signal_0)
576 * Shutdown process. Driver should close everything
577 * already and waits for our process to complete. Free
578 * memory allocared here and kindly return.
580 // unit->deinitialize(unit);
581 CloseDevice((struct IORequest *)unit->e1ku_TimerSlowReq);
582 DeleteIORequest((struct IORequest *)unit->e1ku_TimerSlowReq);
583 DeleteMsgPort(unit->e1ku_TimerSlowPort);
584 DeleteMsgPort(input);
585 DeleteMsgPort(reply_port);
587 D(bug("[%s] e1000func_Schedular: Process shutdown.\n", unit->e1ku_name));
588 return;
590 else if (recvd & (1 << input->mp_SigBit))
592 struct IOSana2Req *io;
594 /* Handle incoming transactions */
595 while ((io = (struct IOSana2Req *)GetMsg(input))!= NULL)
597 D(bug("[%s] e1000func_Schedular: Handle incomming transaction.\n", unit->e1ku_name));
598 ObtainSemaphore(&unit->e1ku_unit_lock);
599 handle_request(LIBBASE, io);
602 else
604 D(bug("[%s] e1000func_Schedular: Handle incomming signal.\n", unit->e1ku_name));
605 /* Handle incoming signals */
612 AROS_USERFUNC_EXIT
616 * Create new e1000 ethernet device unit
618 /* TODO: Handle cleanup on failure in CreateUnit more elegantly */
619 struct e1000Unit *CreateUnit(struct e1000Base *e1KBase, OOP_Object *pciDevice)
621 struct e1000Unit *unit;
622 // UWORD eeprom_data = 0;
623 // UWORD eeprom_apme_mask = E1000_EEPROM_APME;
624 BOOL success = TRUE;
625 int i;
627 D(bug("[e1000] CreateUnit()\n"));
629 if ((unit = AllocMem(sizeof(struct e1000Unit), MEMF_PUBLIC | MEMF_CLEAR)) != NULL)
631 IPTR DeviceID,
632 RevisionID,
633 BaseAddr,
634 BaseType,
635 BaseLen,
636 IOBase = (IPTR)NULL,
637 Flash_Base = (IPTR)NULL,
638 MMIO_Base = (IPTR)NULL,
639 Flash_Size = 0,
640 MMIO_Size = 0,
641 PCIe_Cap = 0;
642 OOP_Object *driver;
644 unit->e1ku_UnitNum = e1KBase->e1kb_UnitCount++;
646 unit->e1ku_Sana2Info.HardwareType = S2WireType_Ethernet;
647 unit->e1ku_Sana2Info.MTU = ETH_MTU;
648 unit->e1ku_Sana2Info.AddrFieldSize = 8 * ETH_ADDRESSSIZE;
650 if ((unit->e1ku_Private00 = (IPTR)AllocMem(sizeof(struct e1000_hw), MEMF_PUBLIC | MEMF_CLEAR)) == (IPTR)NULL)
652 FreeMem(unit, sizeof(struct e1000Unit));
653 return NULL;
656 if ((unit->e1ku_hw_stats = (struct e1000_hw_stats *)AllocMem(sizeof(struct e1000_hw_stats), MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
658 FreeMem((APTR)unit->e1ku_Private00, sizeof(struct e1000_hw));
659 FreeMem(unit, sizeof(struct e1000Unit));
660 return NULL;
663 ((struct e1000_hw *)unit->e1ku_Private00)->back = unit;
665 if ((unit->e1ku_name = AllocVec(6 + (unit->e1ku_UnitNum/10) + 2, MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
667 FreeMem(unit->e1ku_hw_stats, sizeof(struct e1000_hw_stats));
668 FreeMem((APTR)unit->e1ku_Private00, sizeof(struct e1000_hw));
669 FreeMem(unit, sizeof(struct e1000Unit));
670 return NULL;
673 sprintf((char *)unit->e1ku_name, "e1000.%d", unit->e1ku_UnitNum);
675 OOP_GetAttr(pciDevice, aHidd_PCIDevice_ProductID, &DeviceID);
676 OOP_GetAttr(pciDevice, aHidd_PCIDevice_RevisionID, &RevisionID);
677 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Driver, (APTR)&driver);
679 OOP_GetAttr(pciDevice, aHidd_PCIDevice_CapabilityPCIE, (APTR)&PCIe_Cap);
681 unit->e1ku_device = e1KBase;
682 ((struct e1000_hw *)unit->e1ku_Private00)->device_id = DeviceID;
683 ((struct e1000_hw *)unit->e1ku_Private00)->revision_id = RevisionID;
685 unit->e1ku_PCIeCap = (UWORD)PCIe_Cap;
687 unit->e1ku_mtu = unit->e1ku_Sana2Info.MTU;
688 unit->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
689 unit->e1ku_frame_max = unit->e1ku_mtu + ETH_HEADERSIZE + ETH_CRCSIZE;
690 unit->e1ku_frame_min = 60 + ETH_CRCSIZE;
692 unit->e1ku_PCIDevice = pciDevice;
693 unit->e1ku_PCIDriver = driver;
695 InitSemaphore(&unit->e1ku_unit_lock);
696 NEWLIST(&unit->e1ku_Openers);
697 NEWLIST(&unit->e1ku_multicast_ranges);
698 NEWLIST(&unit->e1ku_type_trackers);
700 OOP_GetAttr(pciDevice, aHidd_PCIDevice_INTLine, &unit->e1ku_IRQ);
701 D(bug("[%s] CreateUnit: Device IRQ : %d\n", unit->e1ku_name, unit->e1ku_IRQ));
703 for (i = 1; i <= 5; i++)
705 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Base0 + (i * 3), &BaseAddr);
706 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Type0 + (i * 3), &BaseType);
707 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Size0 + (i * 3), &BaseLen);
708 if ((BaseAddr != (IPTR)NULL) && (BaseLen > 0))
710 if (BaseType & ADDRF_IO)
712 IOBase = BaseAddr;
713 D(bug("[%s] CreateUnit: Device IO @ %p [%d bytes]\n", unit->e1ku_name, IOBase, BaseLen));
715 else
717 Flash_Base = BaseAddr;
718 Flash_Size = BaseLen;
719 D(bug("[%s] CreateUnit: Device Flash @ %p [%d bytes]\n", unit->e1ku_name, Flash_Base, Flash_Size));
724 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Base0, &MMIO_Base);
725 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Size0, &MMIO_Size);
726 D(bug("[%s] CreateUnit: Device MMIO @ %p\n", unit->e1ku_name, MMIO_Base));
728 ((struct e1000_hw *)unit->e1ku_Private00)->io_base = (unsigned long)IOBase;
729 ((struct e1000_hw *)unit->e1ku_Private00)->hw_addr = (UBYTE *)HIDD_PCIDriver_MapPCI(driver, (APTR)MMIO_Base, MMIO_Size);
730 unit->e1ku_MMIOSize = MMIO_Size;
732 D(bug("[%s] CreateUnit: Mapped MMIO @ %p [%d bytes]\n", unit->e1ku_name, ((struct e1000_hw *)unit->e1ku_Private00)->hw_addr, unit->e1ku_MMIOSize));
734 ((struct e1000_hw *)unit->e1ku_Private00)->flash_address = (UBYTE *)HIDD_PCIDriver_MapPCI(driver, (APTR)Flash_Base, Flash_Size);
735 unit->e1ku_FlashSize = Flash_Size;
737 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));
739 if ((((struct e1000_hw *)unit->e1ku_Private00)->io_base) && (((struct e1000_hw *)unit->e1ku_Private00)->hw_addr))
741 struct TagItem attrs[] = {
742 { aHidd_PCIDevice_isIO, TRUE },
743 { aHidd_PCIDevice_isMEM, TRUE },
744 { aHidd_PCIDevice_isMaster, TRUE },
745 { TAG_DONE, 0 },
747 OOP_SetAttrs(pciDevice, (struct TagItem *)&attrs);
749 unit->e1ku_DelayPort.mp_SigBit = SIGB_SINGLE;
750 unit->e1ku_DelayPort.mp_Flags = PA_SIGNAL;
751 unit->e1ku_DelayPort.mp_SigTask = FindTask(NULL);
752 unit->e1ku_DelayPort.mp_Node.ln_Type = NT_MSGPORT;
753 NEWLIST(&unit->e1ku_DelayPort.mp_MsgList);
755 unit->e1ku_DelayReq.tr_node.io_Message.mn_ReplyPort = &unit->e1ku_DelayPort;
756 unit->e1ku_DelayReq.tr_node.io_Message.mn_Length = sizeof(struct timerequest);
758 OpenDevice((STRPTR)"timer.device", UNIT_MICROHZ, (struct IORequest *)&unit->e1ku_DelayReq, 0);
760 /* Call e1000_api.c->e1000_setup_init_funcs */
761 if (e1000_setup_init_funcs((struct e1000_hw *)unit->e1ku_Private00, FALSE) != E1000_SUCCESS)
763 /* Should never have loaded on this device */
764 D(bug("[%s] CreateUnit: Called on unsupported NIC type!!\n", unit->e1ku_name));
765 e1KBase->e1kb_UnitCount = unit->e1ku_UnitNum;
766 FreeVec(unit->e1ku_name);
767 FreeMem((APTR)unit->e1ku_Private00, sizeof(struct e1000_hw));
768 FreeMem(unit, sizeof(struct e1000Unit));
769 return NULL;
772 D(bug("[%s] CreateUnit: Initialised Intel NIC functions..\n", unit->e1ku_name));
774 unit->e1ku_txRing_QueueSize = 1;
775 if ((unit->e1ku_txRing = AllocMem(sizeof(struct e1000_tx_ring) * unit->e1ku_txRing_QueueSize, MEMF_PUBLIC|MEMF_CLEAR)) == NULL)
777 /* TODO: Handle Tx Queue allocation failure more elegantly! */
778 D(bug("[%s] CreateUnit: Failed to Allocate Tx Ring Queue!!!\n", unit->e1ku_name));
779 return NULL;
781 D(bug("[%s] CreateUnit: Queue 0 TxRing @ %p\n", unit->e1ku_name, unit->e1ku_txRing));
783 unit->e1ku_rxRing_QueueSize = 1;
784 if ((unit->e1ku_rxRing = AllocMem(sizeof(struct e1000_rx_ring) * unit->e1ku_rxRing_QueueSize, MEMF_PUBLIC|MEMF_CLEAR)) == NULL)
786 /* TODO: Handle Rx Queue allocation failure more elegantly! */
787 D(bug("[%s] CreateUnit: Failed to Allocate Rx Ring Queue!!!\n", unit->e1ku_name));
788 return NULL;
790 D(bug("[%s] CreateUnit: Queue 0 RxRing @ %p\n", unit->e1ku_name, unit->e1ku_rxRing));
792 e1000func_irq_disable(unit);
793 D(bug("[%s] CreateUnit: e1000 IRQ disabled\n", unit->e1ku_name));
795 if (e1000_init_mac_params((struct e1000_hw *)unit->e1ku_Private00) != E1000_SUCCESS)
797 D(bug("[%s] CreateUnit: Failed to init mac params\n", unit->e1ku_name));
799 D(bug("[%s] CreateUnit: MAC Params Initialised\n", unit->e1ku_name));
801 if (e1000_init_nvm_params((struct e1000_hw *)unit->e1ku_Private00) != E1000_SUCCESS)
803 D(bug("[%s] CreateUnit: Failed to init nvm params\n", unit->e1ku_name));
805 D(bug("[%s] CreateUnit: NVM Params Initialised\n", unit->e1ku_name));
807 if (e1000_init_phy_params((struct e1000_hw *)unit->e1ku_Private00) != E1000_SUCCESS)
809 D(bug("[%s] CreateUnit: Failed to init phy params\n", unit->e1ku_name));
811 D(bug("[%s] CreateUnit: PHY Params Initialised\n", unit->e1ku_name));
813 e1000_get_bus_info((struct e1000_hw *)unit->e1ku_Private00);
815 D(bug("[%s] CreateUnit: Retrieved Bus information..\n", unit->e1ku_name));
817 e1000_init_script_state_82541((struct e1000_hw *)unit->e1ku_Private00, TRUE);
818 e1000_set_tbi_compatibility_82543((struct e1000_hw *)unit->e1ku_Private00, TRUE);
820 D(bug("[%s] CreateUnit: 82541/82543 Setup complete\n", unit->e1ku_name));
822 ((struct e1000_hw *)unit->e1ku_Private00)->phy.autoneg_wait_to_complete = FALSE;
823 ((struct e1000_hw *)unit->e1ku_Private00)->mac.adaptive_ifs = TRUE;
825 /* Copper options */
827 if (((struct e1000_hw *)unit->e1ku_Private00)->phy.media_type == e1000_media_type_copper)
829 ((struct e1000_hw *)unit->e1ku_Private00)->phy.mdix = AUTO_ALL_MODES;
830 ((struct e1000_hw *)unit->e1ku_Private00)->phy.disable_polarity_correction = FALSE;
831 ((struct e1000_hw *)unit->e1ku_Private00)->phy.ms_type = E1000_MASTER_SLAVE;
834 if (e1000_check_reset_block((struct e1000_hw *)unit->e1ku_Private00))
836 D(bug("[%s] CreateUnit: PHY reset is blocked due to SOL/IDER session.\n", unit->e1ku_name));
839 /* Hardware features, flags and workarounds */
840 if (((struct e1000_hw *)unit->e1ku_Private00)->mac.type >= e1000_82540) {
841 unit->e1ku_hwflags |= E1000_FLAG_HAS_SMBUS;
842 unit->e1ku_hwflags |= E1000_FLAG_HAS_INTR_MODERATION;
845 if (((struct e1000_hw *)unit->e1ku_Private00)->mac.type == e1000_82543)
846 unit->e1ku_hwflags |= E1000_FLAG_BAD_TX_CARRIER_STATS_FD;
848 e1000_reset_hw((struct e1000_hw *)unit->e1ku_Private00);
849 D(bug("[%s] CreateUnit: e1000 hardware reset\n", unit->e1ku_name));
851 if (e1000_validate_nvm_checksum((struct e1000_hw *)unit->e1ku_Private00) < 0) {
852 D(bug("[%s] CreateUnit: Warning: The NVM Checksum Is Not Valid!\n", unit->e1ku_name));
853 return NULL;
855 else
857 D(bug("[%s] CreateUnit: NVM Checksum validated successfully\n", unit->e1ku_name));
860 /* copy the MAC address out of the NVM */
862 if (e1000_read_mac_addr((struct e1000_hw *)unit->e1ku_Private00))
864 D(bug("[%s] CreateUnit: NVM Read Error\n", unit->e1ku_name));
866 else
868 D(bug("[%s] CreateUnit: MAC Address Read\n", unit->e1ku_name));
870 memcpy(unit->e1ku_org_addr, ((struct e1000_hw *)unit->e1ku_Private00)->mac.addr, ETH_ADDRESSSIZE);
871 memcpy(unit->e1ku_dev_addr, unit->e1ku_org_addr, ETH_ADDRESSSIZE);
873 D(bug("[%s] CreateUnit: MAC Address %02x:%02x:%02x:%02x:%02x:%02x\n", unit->e1ku_name,
874 unit->e1ku_dev_addr[0], unit->e1ku_dev_addr[1], unit->e1ku_dev_addr[2],
875 unit->e1ku_dev_addr[3], unit->e1ku_dev_addr[4], unit->e1ku_dev_addr[5]));
878 D(bug("[%s] CreateUnit: (PCI%s:%s:%s)\n", unit->e1ku_name,
879 ((((struct e1000_hw *)unit->e1ku_Private00)->bus.type == e1000_bus_type_pcix) ? "-X" :
880 (((struct e1000_hw *)unit->e1ku_Private00)->bus.type == e1000_bus_type_pci_express ? " Express":"")),
881 ((((struct e1000_hw *)unit->e1ku_Private00)->bus.speed == e1000_bus_speed_2500) ? "2.5Gb/s" :
882 (((struct e1000_hw *)unit->e1ku_Private00)->bus.speed == e1000_bus_speed_133) ? "133MHz" :
883 (((struct e1000_hw *)unit->e1ku_Private00)->bus.speed == e1000_bus_speed_120) ? "120MHz" :
884 (((struct e1000_hw *)unit->e1ku_Private00)->bus.speed == e1000_bus_speed_100) ? "100MHz" :
885 (((struct e1000_hw *)unit->e1ku_Private00)->bus.speed == e1000_bus_speed_66) ? "66MHz" : "33MHz"),
886 ((((struct e1000_hw *)unit->e1ku_Private00)->bus.width == e1000_bus_width_64) ? "64-bit" :
887 (((struct e1000_hw *)unit->e1ku_Private00)->bus.width == e1000_bus_width_pcie_x4) ? "Width x4" :
888 (((struct e1000_hw *)unit->e1ku_Private00)->bus.width == e1000_bus_width_pcie_x1) ? "Width x1" :
889 "32-bit")));
893 struct Message *msg;
895 unit->e1ku_irqhandler.is_Node.ln_Type = NT_INTERRUPT;
896 unit->e1ku_irqhandler.is_Node.ln_Pri = 100;
897 unit->e1ku_irqhandler.is_Node.ln_Name = LIBBASE->e1kb_Device.dd_Library.lib_Node.ln_Name;
898 unit->e1ku_irqhandler.is_Code = (VOID_FUNC)e1000func_IntHandler;
899 unit->e1ku_irqhandler.is_Data = unit;
901 unit->e1ku_touthandler.is_Node.ln_Type = NT_INTERRUPT;
902 unit->e1ku_touthandler.is_Node.ln_Pri = 100;
903 unit->e1ku_touthandler.is_Node.ln_Name = LIBBASE->e1kb_Device.dd_Library.lib_Node.ln_Name;
904 unit->e1ku_touthandler.is_Code = (VOID_FUNC)e1000func_WatchdogHandler;
905 unit->e1ku_touthandler.is_Data = unit;
907 unit->e1ku_tx_int.is_Node.ln_Type = NT_INTERRUPT;
908 unit->e1ku_tx_int.is_Node.ln_Name = unit->e1ku_name;
909 unit->e1ku_tx_int.is_Code = (VOID_FUNC)e1000func_TX_Int;
910 unit->e1ku_tx_int.is_Data = unit;
912 for (i = 0; i < REQUEST_QUEUE_COUNT; i++)
914 struct MsgPort *port;
916 if ((port = AllocMem(sizeof(struct MsgPort), MEMF_PUBLIC | MEMF_CLEAR)) == NULL) success = FALSE;
918 if (success)
920 unit->e1ku_request_ports[i] = port;
921 NEWLIST(&port->mp_MsgList);
922 port->mp_Flags = PA_IGNORE;
923 port->mp_SigTask = &unit->e1ku_tx_int;
927 unit->e1ku_request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
929 if (success)
931 struct e1000Startup *sm_UD;
932 UBYTE tmpbuff[100];
934 if ((sm_UD = AllocMem(sizeof(struct e1000Startup), MEMF_PUBLIC | MEMF_CLEAR)) != NULL)
936 sprintf((char *)tmpbuff, e1000_TASK_NAME, unit->e1ku_name);
938 sm_UD->e1ksm_SyncPort = CreateMsgPort();
939 sm_UD->e1ksm_Unit = unit;
941 unit->e1ku_Process = CreateNewProcTags(
942 NP_Entry, (IPTR)e1000func_Schedular,
943 NP_Name, tmpbuff,
944 NP_Synchronous , FALSE,
945 NP_Priority, 0,
946 NP_UserData, (IPTR)sm_UD,
947 NP_StackSize, 140960,
948 TAG_DONE);
950 WaitPort(sm_UD->e1ksm_SyncPort);
951 msg = GetMsg(sm_UD->e1ksm_SyncPort);
952 ReplyMsg(msg);
953 DeleteMsgPort(sm_UD->e1ksm_SyncPort);
954 FreeMem(sm_UD, sizeof(struct e1000Startup));
956 D(bug("[%s] CreateUnit: Device Initialised. Unit %d @ %p\n", unit->e1ku_name, unit->e1ku_UnitNum, unit));
957 return unit;
962 else
964 if ((((struct e1000_hw *)unit->e1ku_Private00)->io_base) == 0)
966 D(bug("[%s] CreateUnit: PANIC! Couldn't find IO area. Aborting\n", unit->e1ku_name));
969 if ((((struct e1000_hw *)unit->e1ku_Private00)->hw_addr) == NULL)
971 D(bug("[%s] CreateUnit: PANIC! Couldn't get MMIO area. Aborting\n", unit->e1ku_name));
975 DeleteUnit(e1KBase, unit);
976 return NULL;
980 * DeleteUnit - removes selected unit. Frees all resources and structures.
982 * The caller should be sure, that given unit is really ready to be freed.
985 void DeleteUnit(struct e1000Base *e1KBase, struct e1000Unit *unit)
987 int i;
988 if (unit)
990 if (unit->e1ku_Process)
992 Signal(&unit->e1ku_Process->pr_Task, unit->e1ku_signal_0);
995 for (i=0; i < REQUEST_QUEUE_COUNT; i++)
997 if (unit->e1ku_request_ports[i] != NULL)
998 FreeMem(unit->e1ku_request_ports[i], sizeof(struct MsgPort));
1000 unit->e1ku_request_ports[i] = NULL;
1003 if ((struct e1000_hw *)unit->e1ku_Private00)
1005 if (((struct e1000_hw *)unit->e1ku_Private00)->hw_addr)
1007 HIDD_PCIDriver_UnmapPCI(unit->e1ku_PCIDriver,
1008 (APTR)((struct e1000_hw *)unit->e1ku_Private00)->hw_addr,
1009 unit->e1ku_MMIOSize);
1011 FreeMem((APTR)unit->e1ku_Private00, sizeof(struct e1000_hw));
1014 if (unit->e1ku_name)
1015 FreeVec(unit->e1ku_name);
1017 FreeMem(unit, sizeof(struct e1000Unit));
1021 static struct AddressRange *FindMulticastRange(LIBBASETYPEPTR LIBBASE, struct e1000Unit *unit, const UBYTE *lower_bound, const UBYTE *upper_bound)
1023 struct AddressRange *range, *tail;
1024 BOOL found = FALSE;
1026 range = (APTR)unit->e1ku_multicast_ranges.mlh_Head;
1027 tail = (APTR)&unit->e1ku_multicast_ranges.mlh_Tail;
1029 while((range != tail) && !found)
1031 if (memcmp(lower_bound, range->lower_bound, ETH_ADDRESSSIZE) == 0 &&
1032 memcmp(upper_bound, range->upper_bound, ETH_ADDRESSSIZE) == 0)
1033 found = TRUE;
1034 else
1035 range = (APTR)range->node.mln_Succ;
1038 if(!found)
1039 range = NULL;
1041 return range;
1044 BOOL AddMulticastRange(LIBBASETYPEPTR LIBBASE, struct e1000Unit *unit, const UBYTE *lower_bound,
1045 const UBYTE *upper_bound)
1047 struct AddressRange *range;
1049 range = FindMulticastRange(LIBBASE, unit, lower_bound, upper_bound);
1051 if(range != NULL)
1052 range->add_count++;
1053 else
1055 range = AllocMem(sizeof(struct AddressRange), MEMF_PUBLIC);
1056 if(range != NULL)
1058 memcpy(range->lower_bound, lower_bound, ETH_ADDRESSSIZE);
1059 memcpy(range->upper_bound, upper_bound, ETH_ADDRESSSIZE);
1060 range->add_count = 1;
1062 Disable();
1063 AddTail((APTR)&unit->e1ku_multicast_ranges, (APTR)range);
1064 Enable();
1066 if (unit->e1ku_range_count++ == 0)
1068 unit->e1ku_ifflags |= IFF_ALLMULTI;
1069 e1000func_set_multi(unit);
1074 return range != NULL;
1077 BOOL RemMulticastRange(LIBBASETYPEPTR LIBBASE, struct e1000Unit *unit, const UBYTE *lower_bound, const UBYTE *upper_bound)
1079 struct AddressRange *range;
1081 range = FindMulticastRange(LIBBASE, unit, lower_bound, upper_bound);
1083 if(range != NULL)
1085 if(--range->add_count == 0)
1087 Disable();
1088 Remove((APTR)range);
1089 Enable();
1090 FreeMem(range, sizeof(struct AddressRange));
1092 if (--unit->e1ku_range_count == 0)
1094 unit->e1ku_ifflags &= ~IFF_ALLMULTI;
1095 e1000func_set_multi(unit);
1099 return range != NULL;