revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / networks / e1000 / unit.c
blobd48ae6334fde22d28eb452535a6a889f82fa11c7
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;
522 bug("[%s] e1000func_Schedular()\n", unit->e1ku_name);
523 bug("[%s] e1000func_Schedular: Setting device up\n", unit->e1ku_name);
526 reply_port = CreateMsgPort();
527 input = CreateMsgPort();
529 unit->e1ku_input_port = input;
531 unit->e1ku_TimerSlowPort = CreateMsgPort();
533 if (unit->e1ku_TimerSlowPort)
535 unit->e1ku_TimerSlowReq = (struct timerequest *)
536 CreateIORequest((struct MsgPort *)unit->e1ku_TimerSlowPort, sizeof(struct timerequest));
538 if (unit->e1ku_TimerSlowReq)
540 if (!OpenDevice("timer.device", UNIT_VBLANK,
541 (struct IORequest *)unit->e1ku_TimerSlowReq, 0))
543 struct Message *msg = AllocVec(sizeof(struct Message), MEMF_PUBLIC|MEMF_CLEAR);
544 ULONG sigset;
546 D(bug("[%s] e1000func_Schedular: Got VBLANK unit of timer.device\n", unit->e1ku_name));
548 e1000func_reset(unit);
550 msg->mn_ReplyPort = reply_port;
551 msg->mn_Length = sizeof(struct Message);
553 D(bug("[%s] e1000func_Schedular: Setup complete. Sending handshake\n", unit->e1ku_name));
554 PutMsg(sm_UD->e1ksm_SyncPort, msg);
555 WaitPort(reply_port);
556 GetMsg(reply_port);
558 FreeVec(msg);
560 D(bug("[%s] e1000func_Schedular: entering forever loop ... \n", unit->e1ku_name));
562 unit->e1ku_signal_0 = AllocSignal(-1);
563 unit->e1ku_signal_1 = AllocSignal(-1);
564 unit->e1ku_signal_2 = AllocSignal(-1);
565 unit->e1ku_signal_3 = AllocSignal(-1);
567 sigset = 1 << input->mp_SigBit |
568 1 << unit->e1ku_signal_0 |
569 1 << unit->e1ku_signal_1 |
570 1 << unit->e1ku_signal_2 |
571 1 << unit->e1ku_signal_3;
572 for(;;)
574 ULONG recvd = Wait(sigset);
575 if (recvd & unit->e1ku_signal_0)
578 * Shutdown process. Driver should close everything
579 * already and waits for our process to complete. Free
580 * memory allocared here and kindly return.
582 // unit->deinitialize(unit);
583 CloseDevice((struct IORequest *)unit->e1ku_TimerSlowReq);
584 DeleteIORequest((struct IORequest *)unit->e1ku_TimerSlowReq);
585 DeleteMsgPort(unit->e1ku_TimerSlowPort);
586 DeleteMsgPort(input);
587 DeleteMsgPort(reply_port);
589 D(bug("[%s] e1000func_Schedular: Process shutdown.\n", unit->e1ku_name));
590 return;
592 else if (recvd & (1 << input->mp_SigBit))
594 struct IOSana2Req *io;
596 /* Handle incoming transactions */
597 while ((io = (struct IOSana2Req *)GetMsg(input))!= NULL)
599 D(bug("[%s] e1000func_Schedular: Handle incomming transaction.\n", unit->e1ku_name));
600 ObtainSemaphore(&unit->e1ku_unit_lock);
601 handle_request(LIBBASE, io);
604 else
606 D(bug("[%s] e1000func_Schedular: Handle incomming signal.\n", unit->e1ku_name));
607 /* Handle incoming signals */
614 AROS_USERFUNC_EXIT
618 * Create new e1000 ethernet device unit
620 /* TODO: Handle cleanup on failure in CreateUnit more elegantly */
621 struct e1000Unit *CreateUnit(struct e1000Base *e1KBase, OOP_Object *pciDevice)
623 struct e1000Unit *unit;
624 // UWORD eeprom_data = 0;
625 // UWORD eeprom_apme_mask = E1000_EEPROM_APME;
626 BOOL success = TRUE;
627 int i;
629 D(bug("[e1000] CreateUnit()\n"));
631 if ((unit = AllocMem(sizeof(struct e1000Unit), MEMF_PUBLIC | MEMF_CLEAR)) != NULL)
633 IPTR DeviceID,
634 RevisionID,
635 BaseAddr,
636 BaseType,
637 BaseLen,
638 IOBase = (IPTR)NULL,
639 Flash_Base = (IPTR)NULL,
640 MMIO_Base = (IPTR)NULL,
641 Flash_Size = 0,
642 MMIO_Size = 0,
643 PCIe_Cap = 0;
644 OOP_Object *driver;
646 unit->e1ku_UnitNum = e1KBase->e1kb_UnitCount++;
648 unit->e1ku_Sana2Info.HardwareType = S2WireType_Ethernet;
649 unit->e1ku_Sana2Info.MTU = ETH_MTU;
650 unit->e1ku_Sana2Info.AddrFieldSize = 8 * ETH_ADDRESSSIZE;
652 if ((unit->e1ku_Private00 = (IPTR)AllocMem(sizeof(struct e1000_hw), MEMF_PUBLIC | MEMF_CLEAR)) == (IPTR)NULL)
654 FreeMem(unit, sizeof(struct e1000Unit));
655 return NULL;
658 if ((unit->e1ku_hw_stats = (struct e1000_hw_stats *)AllocMem(sizeof(struct e1000_hw_stats), MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
660 FreeMem((APTR)unit->e1ku_Private00, sizeof(struct e1000_hw));
661 FreeMem(unit, sizeof(struct e1000Unit));
662 return NULL;
665 ((struct e1000_hw *)unit->e1ku_Private00)->back = unit;
667 if ((unit->e1ku_name = AllocVec(6 + (unit->e1ku_UnitNum/10) + 2, MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
669 FreeMem(unit->e1ku_hw_stats, sizeof(struct e1000_hw_stats));
670 FreeMem((APTR)unit->e1ku_Private00, sizeof(struct e1000_hw));
671 FreeMem(unit, sizeof(struct e1000Unit));
672 return NULL;
675 sprintf((char *)unit->e1ku_name, "e1000.%d", unit->e1ku_UnitNum);
677 OOP_GetAttr(pciDevice, aHidd_PCIDevice_ProductID, &DeviceID);
678 OOP_GetAttr(pciDevice, aHidd_PCIDevice_RevisionID, &RevisionID);
679 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Driver, (APTR)&driver);
681 OOP_GetAttr(pciDevice, aHidd_PCIDevice_CapabilityPCIE, (APTR)&PCIe_Cap);
683 unit->e1ku_device = e1KBase;
684 ((struct e1000_hw *)unit->e1ku_Private00)->device_id = DeviceID;
685 ((struct e1000_hw *)unit->e1ku_Private00)->revision_id = RevisionID;
687 unit->e1ku_PCIeCap = (UWORD)PCIe_Cap;
689 unit->e1ku_mtu = unit->e1ku_Sana2Info.MTU;
690 unit->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
691 unit->e1ku_frame_max = unit->e1ku_mtu + ETH_HEADERSIZE + ETH_CRCSIZE;
692 unit->e1ku_frame_min = 60 + ETH_CRCSIZE;
694 unit->e1ku_PCIDevice = pciDevice;
695 unit->e1ku_PCIDriver = driver;
697 InitSemaphore(&unit->e1ku_unit_lock);
698 NEWLIST(&unit->e1ku_Openers);
699 NEWLIST(&unit->e1ku_multicast_ranges);
700 NEWLIST(&unit->e1ku_type_trackers);
702 OOP_GetAttr(pciDevice, aHidd_PCIDevice_INTLine, &unit->e1ku_IRQ);
703 D(bug("[%s] CreateUnit: Device IRQ : %d\n", unit->e1ku_name, unit->e1ku_IRQ));
705 for (i = 1; i <= 5; i++)
707 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Base0 + (i * 3), &BaseAddr);
708 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Type0 + (i * 3), &BaseType);
709 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Size0 + (i * 3), &BaseLen);
710 if ((BaseAddr != (IPTR)NULL) && (BaseLen > 0))
712 if (BaseType & ADDRF_IO)
714 IOBase = BaseAddr;
715 D(bug("[%s] CreateUnit: Device IO @ %p [%d bytes]\n", unit->e1ku_name, IOBase, BaseLen));
717 else
719 Flash_Base = BaseAddr;
720 Flash_Size = BaseLen;
721 D(bug("[%s] CreateUnit: Device Flash @ %p [%d bytes]\n", unit->e1ku_name, Flash_Base, Flash_Size));
726 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Base0, &MMIO_Base);
727 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Size0, &MMIO_Size);
728 D(bug("[%s] CreateUnit: Device MMIO @ %p\n", unit->e1ku_name, MMIO_Base));
730 ((struct e1000_hw *)unit->e1ku_Private00)->io_base = (unsigned long)IOBase;
731 ((struct e1000_hw *)unit->e1ku_Private00)->hw_addr = (UBYTE *)HIDD_PCIDriver_MapPCI(driver, (APTR)MMIO_Base, MMIO_Size);
732 unit->e1ku_MMIOSize = MMIO_Size;
734 D(bug("[%s] CreateUnit: Mapped MMIO @ %p [%d bytes]\n", unit->e1ku_name, ((struct e1000_hw *)unit->e1ku_Private00)->hw_addr, unit->e1ku_MMIOSize));
736 ((struct e1000_hw *)unit->e1ku_Private00)->flash_address = (UBYTE *)HIDD_PCIDriver_MapPCI(driver, (APTR)Flash_Base, Flash_Size);
737 unit->e1ku_FlashSize = Flash_Size;
739 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));
741 if ((((struct e1000_hw *)unit->e1ku_Private00)->io_base) && (((struct e1000_hw *)unit->e1ku_Private00)->hw_addr))
743 struct TagItem attrs[] = {
744 { aHidd_PCIDevice_isIO, TRUE },
745 { aHidd_PCIDevice_isMEM, TRUE },
746 { aHidd_PCIDevice_isMaster, TRUE },
747 { TAG_DONE, 0 },
749 OOP_SetAttrs(pciDevice, (struct TagItem *)&attrs);
751 unit->e1ku_DelayPort.mp_SigBit = SIGB_SINGLE;
752 unit->e1ku_DelayPort.mp_Flags = PA_SIGNAL;
753 unit->e1ku_DelayPort.mp_SigTask = FindTask(NULL);
754 unit->e1ku_DelayPort.mp_Node.ln_Type = NT_MSGPORT;
755 NEWLIST(&unit->e1ku_DelayPort.mp_MsgList);
757 unit->e1ku_DelayReq.tr_node.io_Message.mn_ReplyPort = &unit->e1ku_DelayPort;
758 unit->e1ku_DelayReq.tr_node.io_Message.mn_Length = sizeof(struct timerequest);
760 OpenDevice((STRPTR)"timer.device", UNIT_MICROHZ, (struct IORequest *)&unit->e1ku_DelayReq, 0);
762 /* Call e1000_api.c->e1000_setup_init_funcs */
763 if (e1000_setup_init_funcs((struct e1000_hw *)unit->e1ku_Private00, FALSE) != E1000_SUCCESS)
765 /* Should never have loaded on this device */
766 D(bug("[%s] CreateUnit: Called on unsupported NIC type!!\n", unit->e1ku_name));
767 e1KBase->e1kb_UnitCount = unit->e1ku_UnitNum;
768 FreeVec(unit->e1ku_name);
769 FreeMem((APTR)unit->e1ku_Private00, sizeof(struct e1000_hw));
770 FreeMem(unit, sizeof(struct e1000Unit));
771 return NULL;
774 D(bug("[%s] CreateUnit: Initialised Intel NIC functions..\n", unit->e1ku_name));
776 unit->e1ku_txRing_QueueSize = 1;
777 if ((unit->e1ku_txRing = AllocMem(sizeof(struct e1000_tx_ring) * unit->e1ku_txRing_QueueSize, MEMF_PUBLIC|MEMF_CLEAR)) == NULL)
779 /* TODO: Handle Tx Queue allocation failure more elegantly! */
780 D(bug("[%s] CreateUnit: Failed to Allocate Tx Ring Queue!!!\n", unit->e1ku_name));
781 return NULL;
783 D(bug("[%s] CreateUnit: Queue 0 TxRing @ %p\n", unit->e1ku_name, unit->e1ku_txRing));
785 unit->e1ku_rxRing_QueueSize = 1;
786 if ((unit->e1ku_rxRing = AllocMem(sizeof(struct e1000_rx_ring) * unit->e1ku_rxRing_QueueSize, MEMF_PUBLIC|MEMF_CLEAR)) == NULL)
788 /* TODO: Handle Rx Queue allocation failure more elegantly! */
789 D(bug("[%s] CreateUnit: Failed to Allocate Rx Ring Queue!!!\n", unit->e1ku_name));
790 return NULL;
792 D(bug("[%s] CreateUnit: Queue 0 RxRing @ %p\n", unit->e1ku_name, unit->e1ku_rxRing));
794 e1000func_irq_disable(unit);
795 D(bug("[%s] CreateUnit: e1000 IRQ disabled\n", unit->e1ku_name));
797 if (e1000_init_mac_params((struct e1000_hw *)unit->e1ku_Private00) != E1000_SUCCESS)
799 D(bug("[%s] CreateUnit: Failed to init mac params\n", unit->e1ku_name));
801 D(bug("[%s] CreateUnit: MAC Params Initialised\n", unit->e1ku_name));
803 if (e1000_init_nvm_params((struct e1000_hw *)unit->e1ku_Private00) != E1000_SUCCESS)
805 D(bug("[%s] CreateUnit: Failed to init nvm params\n", unit->e1ku_name));
807 D(bug("[%s] CreateUnit: NVM Params Initialised\n", unit->e1ku_name));
809 if (e1000_init_phy_params((struct e1000_hw *)unit->e1ku_Private00) != E1000_SUCCESS)
811 D(bug("[%s] CreateUnit: Failed to init phy params\n", unit->e1ku_name));
813 D(bug("[%s] CreateUnit: PHY Params Initialised\n", unit->e1ku_name));
815 e1000_get_bus_info((struct e1000_hw *)unit->e1ku_Private00);
817 D(bug("[%s] CreateUnit: Retrieved Bus information..\n", unit->e1ku_name));
819 e1000_init_script_state_82541((struct e1000_hw *)unit->e1ku_Private00, TRUE);
820 e1000_set_tbi_compatibility_82543((struct e1000_hw *)unit->e1ku_Private00, TRUE);
822 D(bug("[%s] CreateUnit: 82541/82543 Setup complete\n", unit->e1ku_name));
824 ((struct e1000_hw *)unit->e1ku_Private00)->phy.autoneg_wait_to_complete = FALSE;
825 ((struct e1000_hw *)unit->e1ku_Private00)->mac.adaptive_ifs = TRUE;
827 /* Copper options */
829 if (((struct e1000_hw *)unit->e1ku_Private00)->phy.media_type == e1000_media_type_copper)
831 ((struct e1000_hw *)unit->e1ku_Private00)->phy.mdix = AUTO_ALL_MODES;
832 ((struct e1000_hw *)unit->e1ku_Private00)->phy.disable_polarity_correction = FALSE;
833 ((struct e1000_hw *)unit->e1ku_Private00)->phy.ms_type = E1000_MASTER_SLAVE;
836 if (e1000_check_reset_block((struct e1000_hw *)unit->e1ku_Private00))
838 D(bug("[%s] CreateUnit: PHY reset is blocked due to SOL/IDER session.\n", unit->e1ku_name));
841 /* Hardware features, flags and workarounds */
842 if (((struct e1000_hw *)unit->e1ku_Private00)->mac.type >= e1000_82540) {
843 unit->e1ku_hwflags |= E1000_FLAG_HAS_SMBUS;
844 unit->e1ku_hwflags |= E1000_FLAG_HAS_INTR_MODERATION;
847 if (((struct e1000_hw *)unit->e1ku_Private00)->mac.type == e1000_82543)
848 unit->e1ku_hwflags |= E1000_FLAG_BAD_TX_CARRIER_STATS_FD;
850 e1000_reset_hw((struct e1000_hw *)unit->e1ku_Private00);
851 D(bug("[%s] CreateUnit: e1000 hardware reset\n", unit->e1ku_name));
853 if (e1000_validate_nvm_checksum((struct e1000_hw *)unit->e1ku_Private00) < 0) {
854 D(bug("[%s] CreateUnit: Warning: The NVM Checksum Is Not Valid!\n", unit->e1ku_name));
855 return NULL;
857 else
859 D(bug("[%s] CreateUnit: NVM Checksum validated successfully\n", unit->e1ku_name));
862 /* copy the MAC address out of the NVM */
864 if (e1000_read_mac_addr((struct e1000_hw *)unit->e1ku_Private00))
866 D(bug("[%s] CreateUnit: NVM Read Error\n", unit->e1ku_name));
868 else
870 D(bug("[%s] CreateUnit: MAC Address Read\n", unit->e1ku_name));
872 memcpy(unit->e1ku_org_addr, ((struct e1000_hw *)unit->e1ku_Private00)->mac.addr, ETH_ADDRESSSIZE);
873 memcpy(unit->e1ku_dev_addr, unit->e1ku_org_addr, ETH_ADDRESSSIZE);
875 D(bug("[%s] CreateUnit: MAC Address %02x:%02x:%02x:%02x:%02x:%02x\n", unit->e1ku_name,
876 unit->e1ku_dev_addr[0], unit->e1ku_dev_addr[1], unit->e1ku_dev_addr[2],
877 unit->e1ku_dev_addr[3], unit->e1ku_dev_addr[4], unit->e1ku_dev_addr[5]));
880 D(bug("[%s] CreateUnit: (PCI%s:%s:%s)\n", unit->e1ku_name,
881 ((((struct e1000_hw *)unit->e1ku_Private00)->bus.type == e1000_bus_type_pcix) ? "-X" :
882 (((struct e1000_hw *)unit->e1ku_Private00)->bus.type == e1000_bus_type_pci_express ? " Express":"")),
883 ((((struct e1000_hw *)unit->e1ku_Private00)->bus.speed == e1000_bus_speed_2500) ? "2.5Gb/s" :
884 (((struct e1000_hw *)unit->e1ku_Private00)->bus.speed == e1000_bus_speed_133) ? "133MHz" :
885 (((struct e1000_hw *)unit->e1ku_Private00)->bus.speed == e1000_bus_speed_120) ? "120MHz" :
886 (((struct e1000_hw *)unit->e1ku_Private00)->bus.speed == e1000_bus_speed_100) ? "100MHz" :
887 (((struct e1000_hw *)unit->e1ku_Private00)->bus.speed == e1000_bus_speed_66) ? "66MHz" : "33MHz"),
888 ((((struct e1000_hw *)unit->e1ku_Private00)->bus.width == e1000_bus_width_64) ? "64-bit" :
889 (((struct e1000_hw *)unit->e1ku_Private00)->bus.width == e1000_bus_width_pcie_x4) ? "Width x4" :
890 (((struct e1000_hw *)unit->e1ku_Private00)->bus.width == e1000_bus_width_pcie_x1) ? "Width x1" :
891 "32-bit")));
895 struct Message *msg;
897 unit->e1ku_irqhandler.is_Node.ln_Type = NT_INTERRUPT;
898 unit->e1ku_irqhandler.is_Node.ln_Pri = 100;
899 unit->e1ku_irqhandler.is_Node.ln_Name = LIBBASE->e1kb_Device.dd_Library.lib_Node.ln_Name;
900 unit->e1ku_irqhandler.is_Code = (VOID_FUNC)e1000func_IntHandler;
901 unit->e1ku_irqhandler.is_Data = unit;
903 unit->e1ku_touthandler.is_Node.ln_Type = NT_INTERRUPT;
904 unit->e1ku_touthandler.is_Node.ln_Pri = 100;
905 unit->e1ku_touthandler.is_Node.ln_Name = LIBBASE->e1kb_Device.dd_Library.lib_Node.ln_Name;
906 unit->e1ku_touthandler.is_Code = (VOID_FUNC)e1000func_WatchdogHandler;
907 unit->e1ku_touthandler.is_Data = unit;
909 unit->e1ku_tx_int.is_Node.ln_Type = NT_INTERRUPT;
910 unit->e1ku_tx_int.is_Node.ln_Name = unit->e1ku_name;
911 unit->e1ku_tx_int.is_Code = (VOID_FUNC)e1000func_TX_Int;
912 unit->e1ku_tx_int.is_Data = unit;
914 for (i = 0; i < REQUEST_QUEUE_COUNT; i++)
916 struct MsgPort *port;
918 if ((port = AllocMem(sizeof(struct MsgPort), MEMF_PUBLIC | MEMF_CLEAR)) == NULL) success = FALSE;
920 if (success)
922 unit->e1ku_request_ports[i] = port;
923 NEWLIST(&port->mp_MsgList);
924 port->mp_Flags = PA_IGNORE;
925 port->mp_SigTask = &unit->e1ku_tx_int;
929 unit->e1ku_request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
931 if (success)
933 struct e1000Startup *sm_UD;
934 UBYTE tmpbuff[100];
936 if ((sm_UD = AllocMem(sizeof(struct e1000Startup), MEMF_PUBLIC | MEMF_CLEAR)) != NULL)
938 sprintf((char *)tmpbuff, e1000_TASK_NAME, unit->e1ku_name);
940 sm_UD->e1ksm_SyncPort = CreateMsgPort();
941 sm_UD->e1ksm_Unit = unit;
943 unit->e1ku_Process = CreateNewProcTags(
944 NP_Entry, (IPTR)e1000func_Schedular,
945 NP_Name, tmpbuff,
946 NP_Synchronous , FALSE,
947 NP_Priority, 0,
948 NP_UserData, (IPTR)sm_UD,
949 NP_StackSize, 140960,
950 TAG_DONE);
952 WaitPort(sm_UD->e1ksm_SyncPort);
953 msg = GetMsg(sm_UD->e1ksm_SyncPort);
954 ReplyMsg(msg);
955 DeleteMsgPort(sm_UD->e1ksm_SyncPort);
956 FreeMem(sm_UD, sizeof(struct e1000Startup));
958 D(bug("[%s] CreateUnit: Device Initialised. Unit %d @ %p\n", unit->e1ku_name, unit->e1ku_UnitNum, unit));
959 return unit;
964 else
966 if ((((struct e1000_hw *)unit->e1ku_Private00)->io_base) == 0)
968 D(bug("[%s] CreateUnit: PANIC! Couldn't find IO area. Aborting\n", unit->e1ku_name));
971 if ((((struct e1000_hw *)unit->e1ku_Private00)->hw_addr) == NULL)
973 D(bug("[%s] CreateUnit: PANIC! Couldn't get MMIO area. Aborting\n", unit->e1ku_name));
977 DeleteUnit(e1KBase, unit);
978 return NULL;
982 * DeleteUnit - removes selected unit. Frees all resources and structures.
984 * The caller should be sure, that given unit is really ready to be freed.
987 void DeleteUnit(struct e1000Base *e1KBase, struct e1000Unit *unit)
989 int i;
990 if (unit)
992 if (unit->e1ku_Process)
994 Signal(&unit->e1ku_Process->pr_Task, unit->e1ku_signal_0);
997 for (i=0; i < REQUEST_QUEUE_COUNT; i++)
999 if (unit->e1ku_request_ports[i] != NULL)
1000 FreeMem(unit->e1ku_request_ports[i], sizeof(struct MsgPort));
1002 unit->e1ku_request_ports[i] = NULL;
1005 if ((struct e1000_hw *)unit->e1ku_Private00)
1007 if (((struct e1000_hw *)unit->e1ku_Private00)->hw_addr)
1009 HIDD_PCIDriver_UnmapPCI(unit->e1ku_PCIDriver,
1010 (APTR)((struct e1000_hw *)unit->e1ku_Private00)->hw_addr,
1011 unit->e1ku_MMIOSize);
1013 FreeMem((APTR)unit->e1ku_Private00, sizeof(struct e1000_hw));
1016 if (unit->e1ku_name)
1017 FreeVec(unit->e1ku_name);
1019 FreeMem(unit, sizeof(struct e1000Unit));
1023 static struct AddressRange *FindMulticastRange(LIBBASETYPEPTR LIBBASE, struct e1000Unit *unit, const UBYTE *lower_bound, const UBYTE *upper_bound)
1025 struct AddressRange *range, *tail;
1026 BOOL found = FALSE;
1028 range = (APTR)unit->e1ku_multicast_ranges.mlh_Head;
1029 tail = (APTR)&unit->e1ku_multicast_ranges.mlh_Tail;
1031 while((range != tail) && !found)
1033 if (memcmp(lower_bound, range->lower_bound, ETH_ADDRESSSIZE) == 0 &&
1034 memcmp(upper_bound, range->upper_bound, ETH_ADDRESSSIZE) == 0)
1035 found = TRUE;
1036 else
1037 range = (APTR)range->node.mln_Succ;
1040 if(!found)
1041 range = NULL;
1043 return range;
1046 BOOL AddMulticastRange(LIBBASETYPEPTR LIBBASE, struct e1000Unit *unit, const UBYTE *lower_bound,
1047 const UBYTE *upper_bound)
1049 struct AddressRange *range;
1051 range = FindMulticastRange(LIBBASE, unit, lower_bound, upper_bound);
1053 if(range != NULL)
1054 range->add_count++;
1055 else
1057 range = AllocMem(sizeof(struct AddressRange), MEMF_PUBLIC);
1058 if(range != NULL)
1060 memcpy(range->lower_bound, lower_bound, ETH_ADDRESSSIZE);
1061 memcpy(range->upper_bound, upper_bound, ETH_ADDRESSSIZE);
1062 range->add_count = 1;
1064 Disable();
1065 AddTail((APTR)&unit->e1ku_multicast_ranges, (APTR)range);
1066 Enable();
1068 if (unit->e1ku_range_count++ == 0)
1070 unit->e1ku_ifflags |= IFF_ALLMULTI;
1071 e1000func_set_multi(unit);
1076 return range != NULL;
1079 BOOL RemMulticastRange(LIBBASETYPEPTR LIBBASE, struct e1000Unit *unit, const UBYTE *lower_bound, const UBYTE *upper_bound)
1081 struct AddressRange *range;
1083 range = FindMulticastRange(LIBBASE, unit, lower_bound, upper_bound);
1085 if(range != NULL)
1087 if(--range->add_count == 0)
1089 Disable();
1090 Remove((APTR)range);
1091 Enable();
1092 FreeMem(range, sizeof(struct AddressRange));
1094 if (--unit->e1ku_range_count == 0)
1096 unit->e1ku_ifflags &= ~IFF_ALLMULTI;
1097 e1000func_set_multi(unit);
1101 return range != NULL;