6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
22 #include <exec/types.h>
23 #include <exec/resident.h>
25 #include <exec/errors.h>
26 #include <exec/lists.h>
28 #include <aros/libcall.h>
29 #include <aros/symbolsets.h>
33 #include <devices/sana2.h>
34 #include <devices/sana2specialstats.h>
36 #include <utility/utility.h>
37 #include <utility/tagitem.h>
38 #include <utility/hooks.h>
42 #include <proto/oop.h>
43 #include <proto/exec.h>
44 #include <proto/utility.h>
49 #include "e1000_api.h"
51 #include LC_LIBDEFS_FILE
59 struct pci_device_ids e1000_devices
[] =
61 { (E1000_DEV_ID_82542
), "82542" },
62 { (E1000_DEV_ID_82543GC_FIBER
), "82543GC (Fiber)" },
63 { (E1000_DEV_ID_82543GC_COPPER
), "82543GC (Copper)" },
64 { (E1000_DEV_ID_82544EI_COPPER
), "82544EI (Copper)" },
65 { (E1000_DEV_ID_82544EI_FIBER
), "82544EI (Fiber)" },
66 { (E1000_DEV_ID_82544GC_COPPER
), "82544GC (Copper)" },
67 { (E1000_DEV_ID_82544GC_LOM
), "82544GC (LOM)" },
68 { (E1000_DEV_ID_82540EM
), "82540EM" },
69 { (E1000_DEV_ID_82545EM_COPPER
), "82545EM (Copper)" },
70 { (E1000_DEV_ID_82546EB_COPPER
), "82546EB (Copper)" },
71 { (E1000_DEV_ID_82545EM_FIBER
), "82545EM (Fiber)" },
72 { (E1000_DEV_ID_82546EB_FIBER
), "82546EB (Fiber)" },
73 { (E1000_DEV_ID_82541EI
), "82541EI" },
74 { (E1000_DEV_ID_82541ER_LOM
), "82541ER (LOM)" },
75 { (E1000_DEV_ID_82540EM_LOM
), "82540EM (LOM)" },
76 { (E1000_DEV_ID_82540EP_LOM
), "82540EP (LOM)" },
77 { (E1000_DEV_ID_82540EP
), "82540EP" },
78 { (E1000_DEV_ID_82541EI_MOBILE
), "82541EI (Mobile)" },
79 { (E1000_DEV_ID_82547EI
), "82547EI" },
80 { (E1000_DEV_ID_82547EI_MOBILE
), "82547EI (Mobile)" },
81 { (E1000_DEV_ID_82546EB_QUAD_COPPER
), "82546EB (Quad Copper)" },
82 { (E1000_DEV_ID_82540EP_LP
), "82540EP (LP)" },
83 { (E1000_DEV_ID_82545GM_COPPER
), "82545GM (Copper)" },
84 { (E1000_DEV_ID_82545GM_FIBER
), "82545GM (Fiber)" },
85 { (E1000_DEV_ID_82545GM_SERDES
), "82545GM (Serdes)" },
86 { (E1000_DEV_ID_82547GI
), "82547GI" },
87 { (E1000_DEV_ID_82541GI
), "82541GI" },
88 { (E1000_DEV_ID_82541GI_MOBILE
), "82541GI (Mobile)" },
89 { (E1000_DEV_ID_82541ER
), "82541ER" },
90 { (E1000_DEV_ID_82546GB_COPPER
), "82546GB (Copper)" },
91 { (E1000_DEV_ID_82546GB_FIBER
), "82546GB (Fiber)" },
92 { (E1000_DEV_ID_82546GB_SERDES
), "82546GB (Serdes)" },
93 { (E1000_DEV_ID_82541GI_LF
), "82541GI (LF)" },
94 { (E1000_DEV_ID_82546GB_PCIE
), "82546GB (PCI-E)" },
95 { (E1000_DEV_ID_82546GB_QUAD_COPPER
), "82546GB (Quad Copper)" },
96 { (E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3
), "82546GB (Quad Copper KSP3)" },
100 AROS_UFH3(void, PCI_Enumerator
,
101 AROS_UFHA(struct Hook
*, hook
, A0
),
102 AROS_UFHA(OOP_Object
*, pciDevice
, A2
),
103 AROS_UFHA(APTR
, message
, A1
))
107 struct e1000Unit
*unit
;
111 D(bug("[e1000] PCI_Enumerator()\n"));
113 LIBBASETYPEPTR LIBBASE
= (LIBBASETYPEPTR
)hook
->h_Data
;
115 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_ProductID
, &DeviceID
);
117 while(e1000_devices
[devid_count
].deviceid
!= (IPTR
)NULL
)
119 if (DeviceID
== e1000_devices
[devid_count
].deviceid
)
121 D(bug("[e1000] PCI_Enumerator: Found %s e1000 NIC, ProductID = %04x\n", e1000_devices
[devid_count
].devicename
, DeviceID
));
123 if ((unit
= CreateUnit(LIBBASE
, pciDevice
)) != NULL
)
125 AddTail(&LIBBASE
->e1kb_Units
, &unit
->e1ku_Node
);
129 D(bug("[e1000] PCI_Enumerator: Failed to create unit!\n"));
139 static int GM_UNIQUENAME(Init
)(LIBBASETYPEPTR LIBBASE
)
141 D(bug("[e1000] Init()\n"));
144 sprintf((char *)tmpbuff
, e1000_TASK_NAME
, "e1000.0");
146 if (FindTask(tmpbuff
) != NULL
)
148 D(bug("[e1000] device already up and running.\n"));
152 NEWLIST(&LIBBASE
->e1kb_Units
);
154 LIBBASE
->e1kb_PCIDeviceAttrBase
= OOP_ObtainAttrBase(IID_Hidd_PCIDevice
);
156 if (LIBBASE
->e1kb_PCIDeviceAttrBase
!= 0)
158 D(bug("[e1000] HiddPCIDeviceAttrBase @ %p\n", LIBBASE
->e1kb_PCIDeviceAttrBase
));
160 LIBBASE
->e1kb_PCI
= OOP_NewObject(NULL
, CLID_Hidd_PCI
, NULL
);
162 if (LIBBASE
->e1kb_PCI
)
164 D(bug("[e1000] PCI Subsystem HIDD object @ %p\n", LIBBASE
->e1kb_PCI
));
166 struct Hook FindHook
= {
167 h_Entry
: (IPTR (*)())PCI_Enumerator
,
171 struct TagItem Requirements
[] = {
172 { tHidd_PCI_VendorID
, 0x8086 },
176 HIDD_PCI_EnumDevices(LIBBASE
->e1kb_PCI
,
178 (struct TagItem
*)&Requirements
181 if (!(IsListEmpty(&LIBBASE
->e1kb_Units
)))
191 static int GM_UNIQUENAME(Expunge
)(LIBBASETYPEPTR LIBBASE
)
193 D(bug("[e1000] Expunge()\n"));
195 struct e1000Unit
*unit_current
, *unit_tmp
;
197 if (!(IsListEmpty(&LIBBASE
->e1kb_Units
)))
199 ForeachNodeSafe(&LIBBASE
->e1kb_Units
, unit_current
, unit_tmp
)
201 DeleteUnit(LIBBASE
, unit_current
);
205 if (LIBBASE
->e1kb_PCIDeviceAttrBase
!= 0)
206 OOP_ReleaseAttrBase(IID_Hidd_PCIDevice
);
208 LIBBASE
->e1kb_PCIDeviceAttrBase
= 0;
210 if (LIBBASE
->e1kb_PCI
!= NULL
)
211 OOP_DisposeObject(LIBBASE
->e1kb_PCI
);
216 static const ULONG rx_tags
[] = {
221 static const ULONG tx_tags
[] = {
227 static int GM_UNIQUENAME(Open
)
229 LIBBASETYPEPTR LIBBASE
,
230 struct IOSana2Req
* req
,
235 struct TagItem
*tags
;
236 struct e1000Unit
*unit
= NULL
, *unit_current
;
237 struct Opener
*opener
;
241 if (!(IsListEmpty(&LIBBASE
->e1kb_Units
)))
243 ForeachNode(&LIBBASE
->e1kb_Units
, unit_current
)
245 if (unit_current
->e1ku_UnitNum
== unitnum
)
250 D(bug("[e1000] OpenDevice(%d)\n", unitnum
));
254 D(bug("[e1000] OpenDevice: Unit %d @ %p\n", unitnum
, unit
));
255 req
->ios2_Req
.io_Unit
= NULL
;
256 tags
= req
->ios2_BufferManagement
;
258 req
->ios2_BufferManagement
= NULL
;
260 /* Check request size */
261 if(req
->ios2_Req
.io_Message
.mn_Length
< sizeof(struct IOSana2Req
))
262 error
= IOERR_OPENFAIL
;
264 req
->ios2_Req
.io_Unit
= (APTR
)unit
;
266 /* Handle device sharing */
269 if(unit
->e1ku_open_count
!= 0 && ((unit
->e1ku_ifflags
& IFF_SHARED
) == 0 ||
270 (flags
& SANA2OPF_MINE
) != 0))
272 error
= IOERR_UNITBUSY
;
276 unit
->e1ku_open_count
++;
282 if((flags
& SANA2OPF_MINE
) == 0)
283 unit
->e1ku_ifflags
|= IFF_SHARED
;
284 else if((flags
& SANA2OPF_PROM
) != 0)
285 unit
->e1ku_ifflags
|= IFF_PROMISC
;
287 /* Set up buffer-management structure and get hooks */
288 opener
= AllocVec(sizeof(struct Opener
), MEMF_PUBLIC
| MEMF_CLEAR
);
289 req
->ios2_BufferManagement
= (APTR
)opener
;
292 error
= IOERR_OPENFAIL
;
297 NEWLIST(&opener
->read_port
.mp_MsgList
);
298 opener
->read_port
.mp_Flags
= PA_IGNORE
;
299 NEWLIST((APTR
)&opener
->initial_stats
);
301 for(i
= 0; i
< 2; i
++)
302 opener
->rx_function
= (APTR
)GetTagData(rx_tags
[i
], (IPTR
)opener
->rx_function
, tags
);
303 for(i
= 0; i
< 3; i
++)
304 opener
->tx_function
= (APTR
)GetTagData(tx_tags
[i
], (IPTR
)opener
->tx_function
, tags
);
306 opener
->filter_hook
= (APTR
)GetTagData(S2_PacketFilter
, 0, tags
);
309 AddTail((APTR
)&unit
->e1ku_Openers
, (APTR
)opener
);
314 CloseDevice((struct IORequest
*)req
);
317 D(bug("[e1000] OpenDevice: Starting Unit %d\n", unitnum
));
318 ULONG rx_ring_count
, tx_ring_count
;
319 enum e1000_mac_type mac_type
;
321 mac_type
= ((struct e1000_hw
*)unit
->e1ku_Private00
)->mac
.type
;
323 ((struct e1000_hw
*)unit
->e1ku_Private00
)->mac
.autoneg
= AUTONEG_ENABLE
;
324 if (((struct e1000_hw
*)unit
->e1ku_Private00
)->phy
.media_type
== e1000_media_type_fiber
)
325 ((struct e1000_hw
*)unit
->e1ku_Private00
)->phy
.autoneg_advertised
= ADVERTISED_1000baseT_Full
| ADVERTISED_FIBRE
| ADVERTISED_Autoneg
;
327 ((struct e1000_hw
*)unit
->e1ku_Private00
)->phy
.autoneg_advertised
= ADVERTISED_TP
| ADVERTISED_Autoneg
;
328 ((struct e1000_hw
*)unit
->e1ku_Private00
)->fc
.requested_mode
= e1000_fc_default
;
330 rx_ring_count
= max((ULONG
)E1000_DEFAULT_RXD
,(ULONG
)E1000_MIN_RXD
);
331 rx_ring_count
= min(rx_ring_count
,(ULONG
)(mac_type
< e1000_82544
?
332 E1000_MAX_RXD
: E1000_MAX_82544_RXD
));
333 rx_ring_count
= ALIGN(rx_ring_count
, REQ_RX_DESCRIPTOR_MULTIPLE
);
335 tx_ring_count
= max((ULONG
)E1000_DEFAULT_TXD
,(ULONG
)E1000_MIN_TXD
);
336 tx_ring_count
= min(tx_ring_count
,(ULONG
)(mac_type
< e1000_82544
?
337 E1000_MAX_TXD
: E1000_MAX_82544_TXD
));
338 tx_ring_count
= ALIGN(tx_ring_count
, REQ_TX_DESCRIPTOR_MULTIPLE
);
340 /* overwrite the counts with the new values */
341 for (i
= 0; i
< unit
->e1ku_txRing_QueueSize
; i
++)
342 unit
->e1ku_txRing
[i
].count
= tx_ring_count
;
344 for (i
= 0; i
< unit
->e1ku_rxRing_QueueSize
; i
++)
345 unit
->e1ku_rxRing
[i
].count
= rx_ring_count
;
347 if (e1000func_setup_all_tx_resources(unit
))
348 error
= IOERR_OPENFAIL
;
350 /* allocate receive descriptors */
351 if ((error
== 0) && (e1000func_setup_all_rx_resources(unit
)))
352 error
= IOERR_OPENFAIL
;
354 if ((error
== 0) && (((struct e1000_hw
*)unit
->e1ku_Private00
)->phy
.media_type
== e1000_media_type_copper
))
355 e1000_power_up_phy((struct e1000_hw
*)unit
->e1ku_Private00
);
358 e1000func_configure(unit
);
360 if ((error
== 0) && (request_irq(unit
)))
362 error
= IOERR_OPENFAIL
;
366 D(bug("[%s] OpenDevice: IRQ Attached\n", unit
->e1ku_name
));
372 D(bug("[e1000] OpenDevice: Invalid Unit! (unitno = %d)\n", unitnum
));
373 error
= IOERR_OPENFAIL
;
376 req
->ios2_Req
.io_Error
= error
;
378 return (error
!= 0) ? FALSE
: TRUE
;
381 static int GM_UNIQUENAME(Close
)
383 LIBBASETYPEPTR LIBBASE
,
384 struct IOSana2Req
* req
387 struct e1000Unit
*unit
= (struct e1000Unit
*)req
->ios2_Req
.io_Unit
;
388 struct Opener
*opener
;
390 D(bug("[e1000] CloseDevice(unit @ %p, unitno %d)\n", unit
, unit
->e1ku_UnitNum
));
392 /* FIXME: CloseDevice->stop */
396 opener
= (APTR
)req
->ios2_BufferManagement
;
397 if ((APTR
)req
->ios2_BufferManagement
!= NULL
)
400 Remove((struct Node
*)opener
);
409 ADD2INITLIB(GM_UNIQUENAME(Init
),0)
410 ADD2EXPUNGELIB(GM_UNIQUENAME(Expunge
),0)
411 ADD2OPENDEV(GM_UNIQUENAME(Open
),0)
412 ADD2CLOSEDEV(GM_UNIQUENAME(Close
),0)
414 AROS_LH1(void, beginio
,
415 AROS_LHA(struct IOSana2Req
*, req
, A1
),
416 LIBBASETYPEPTR
, LIBBASE
, 5, e1000
)
419 struct e1000Unit
*unit
;
421 D(bug("[e1000] BeginIO()\n"));
423 req
->ios2_Req
.io_Error
= 0;
424 if ((unit
= (APTR
)req
->ios2_Req
.io_Unit
) != NULL
)
426 D(bug("[e1000] BeginIO: unit @ %p\n", unit
));
428 if (AttemptSemaphore(&unit
->e1ku_unit_lock
))
430 D(bug("[e1000] BeginIO: Calling handle_request()\n"));
431 handle_request(LIBBASE
, req
);
435 D(bug("[e1000] BeginIO: Queueing request\n"));
436 req
->ios2_Req
.io_Flags
&= ~IOF_QUICK
;
437 PutMsg(unit
->e1ku_input_port
, (struct Message
*)req
);
443 AROS_LH1(LONG
, abortio
,
444 AROS_LHA(struct IOSana2Req
*, req
, A1
),
445 LIBBASETYPEPTR
, LIBBASE
, 6, e1000
)
448 struct e1000Unit
*unit
;
450 D(bug("[e1000] AbortIO()\n"));
452 if ((unit
= (APTR
)req
->ios2_Req
.io_Unit
) != NULL
)
455 if ((req
->ios2_Req
.io_Message
.mn_Node
.ln_Type
== NT_MESSAGE
) &&
456 (req
->ios2_Req
.io_Flags
& IOF_QUICK
) == 0)
458 Remove((struct Node
*)req
);
459 req
->ios2_Req
.io_Error
= IOERR_ABORTED
;
460 req
->ios2_WireError
= S2WERR_GENERIC_ERROR
;
461 ReplyMsg((struct Message
*)req
);