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,
21 #include <exec/types.h>
22 #include <exec/resident.h>
24 #include <exec/ports.h>
25 #include <exec/errors.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>
48 #include "e1000_api.h"
49 #include "e1000_defines.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
;
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 */
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
);
84 struct TypeStats
*FindTypeStats(struct e1000Base
*e1KBase
, struct e1000Unit
*unit
,
85 struct MinList
*list
, ULONG packet_type
)
87 struct TypeStats
*stats
, *tail
;
90 stats
= (APTR
)list
->mlh_Head
;
91 tail
= (APTR
)&list
->mlh_Tail
;
93 while(stats
!= tail
&& !found
)
95 if(stats
->packet_type
== packet_type
)
98 stats
= (APTR
)stats
->node
.mln_Succ
;
107 void FlushUnit(LIBBASETYPEPTR LIBBASE
, struct e1000Unit
*unit
, UBYTE last_queue
, BYTE error
)
109 struct IORequest
*request
;
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
)
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
;
160 ULONG txd_upper
= 0, txd_lower
= E1000_TXD_CMD_IFCS
;
161 UWORD packet_size
, data_size
;
162 UBYTE
*buffer
, error
;
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
|
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
)))
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
));
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
;
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
238 /* Now the packet is already in TX buffer, update flags for NIC */
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 */
248 D(bug("[%s]: Tx Buffer %d Packet Dump -:", unit
->e1ku_name
, i
));
249 for (j
=0; j
<64; j
++) {
251 D(bug("\n[%s]: %03x:", unit
->e1ku_name
, j
));
252 D(bug(" %02x", ((unsigned char*)frame
)[j
]));
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;
276 request
->ios2_Req
.io_Error
= error
;
277 request
->ios2_WireError
= wire_error
;
279 Remove((APTR
)request
);
281 ReplyMsg((APTR
)request
);
283 /* Update statistics */
286 tracker
= FindTypeStats(LIBBASE
, unit
, &unit
->e1ku_type_trackers
, request
->ios2_PacketType
);
290 tracker
->stats
.PacketsSent
++;
291 tracker
->stats
.BytesSent
+= packet_size
;
296 tx_ring
->next_to_use
= i
;
306 AROS_INTH1(e1000func_WatchdogHandler
,struct e1000Unit
*,unit
)
310 struct Device
*TimerBase
= unit
->e1ku_TimerSlowReq
->tr_node
.io_Device
;
314 //D(bug("[%s]: ## e1000func_WatchdogHandler()\n", unit->e1ku_name));
317 * If timeout timer is expected, and time elapsed - regenerate the
320 if (unit
->e1ku_toutNEED
&& (CmpTime(&time
, &unit
->e1ku_toutPOLL
) < 0))
322 unit
->e1ku_toutNEED
= FALSE
;
323 //Cause(&unit->e1ku_tx_end_int);
332 * The interrupt handler - schedules code execution to proper handlers depending
333 * on the message from e1000.
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
)
347 struct Device
*TimerBase
= unit
->e1ku_TimerSlowReq
->tr_node
.io_Device
;
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
));
357 D(bug("Skipping\n"));
358 return FALSE
; /* Not our interrupt */
361 D(bug("Processing ..\n"));
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
++) {
373 for (j
= 0; j
< unit
->e1ku_rxRing_QueueSize
; j
++)
374 rx_cleaned
|= e1000func_clean_rx_irq(unit
, &unit
->e1ku_rxRing
[j
]);
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
)
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
);
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
;
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];
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
));
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
));
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
);
465 D(bug("SUCCESS!!\n"));
468 Remove((APTR
)request
);
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
;
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
;
491 while((range
!= tail
) && !accept
)
493 if ((memcmp(address
, range
->lower_bound
, ETH_ADDRESSSIZE
) >= 0) &&
494 (memcmp(address
, range
->upper_bound
, ETH_ADDRESSSIZE
) <= 0))
496 range
= (APTR
)range
->node
.mln_Succ
;
500 unit
->e1ku_special_stats
[S2SS_ETHERNET_BADMULTICAST
& 0xffff]++;
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
))
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
);
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
);
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
;
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
));
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
);
604 D(bug("[%s] e1000func_Schedular: Handle incomming signal.\n", unit
->e1ku_name
));
605 /* Handle incoming signals */
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;
627 D(bug("[e1000] CreateUnit()\n"));
629 if ((unit
= AllocMem(sizeof(struct e1000Unit
), MEMF_PUBLIC
| MEMF_CLEAR
)) != NULL
)
637 Flash_Base
= (IPTR
)NULL
,
638 MMIO_Base
= (IPTR
)NULL
,
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
));
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
));
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
));
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
)
713 D(bug("[%s] CreateUnit: Device IO @ %p [%d bytes]\n", unit
->e1ku_name
, IOBase
, BaseLen
));
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
},
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
));
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
));
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
));
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
;
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
));
857 D(bug("[%s] CreateUnit: NVM Checksum validated succesfully\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
));
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" :
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
;
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
;
931 struct e1000Startup
*sm_UD
;
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
,
944 NP_Synchronous
, FALSE
,
946 NP_UserData
, (IPTR
)sm_UD
,
947 NP_StackSize
, 140960,
950 WaitPort(sm_UD
->e1ksm_SyncPort
);
951 msg
= GetMsg(sm_UD
->e1ksm_SyncPort
);
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
));
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
);
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
)
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
;
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)
1035 range
= (APTR
)range
->node
.mln_Succ
;
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
);
1055 range
= AllocMem(sizeof(struct AddressRange
), MEMF_PUBLIC
);
1058 memcpy(range
->lower_bound
, lower_bound
, ETH_ADDRESSSIZE
);
1059 memcpy(range
->upper_bound
, upper_bound
, ETH_ADDRESSSIZE
);
1060 range
->add_count
= 1;
1063 AddTail((APTR
)&unit
->e1ku_multicast_ranges
, (APTR
)range
);
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
);
1085 if(--range
->add_count
== 0)
1088 Remove((APTR
)range
);
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
;