Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / devs / networks / e1000 / e1000_init.c
blob354482f9db54f27a184977d2b0a6660e78573363
1 /*
2 * $Id$
3 */
5 /*
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,
19 MA 02111-1307, USA.
22 #include <exec/types.h>
23 #include <exec/resident.h>
24 #include <exec/io.h>
25 #include <exec/errors.h>
26 #include <exec/lists.h>
28 #include <aros/libcall.h>
29 #include <aros/symbolsets.h>
31 #include <oop/oop.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>
40 #include <hidd/pci.h>
42 #include <proto/oop.h>
43 #include <proto/exec.h>
44 #include <proto/utility.h>
46 #include <stdio.h>
48 #include "e1000.h"
49 #include "e1000_api.h"
50 #include "unit.h"
51 #include LC_LIBDEFS_FILE
53 struct pci_device_ids
55 IPTR deviceid;
56 char *devicename;
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)" },
97 { (IPTR)NULL, NULL }
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))
105 AROS_USERFUNC_INIT
107 struct e1000Unit *unit;
108 int devid_count = 0;
109 IPTR DeviceID = 0;
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);
127 else
129 D(bug("[e1000] PCI_Enumerator: Failed to create unit!\n"));
131 break;
133 devid_count++;
136 AROS_USERFUNC_EXIT
139 static int GM_UNIQUENAME(Init)(LIBBASETYPEPTR LIBBASE)
141 D(bug("[e1000] Init()\n"));
143 UBYTE tmpbuff[100];
144 sprintf((char *)tmpbuff, e1000_TASK_NAME, "e1000.0");
146 if (FindTask(tmpbuff) != NULL)
148 D(bug("[e1000] device already up and running.\n"));
149 return FALSE;
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,
168 h_Data: LIBBASE,
171 struct TagItem Requirements[] = {
172 { tHidd_PCI_VendorID, 0x8086 },
173 { TAG_DONE, 0UL }
176 HIDD_PCI_EnumDevices(LIBBASE->e1kb_PCI,
177 &FindHook,
178 (struct TagItem *)&Requirements
181 if (!(IsListEmpty(&LIBBASE->e1kb_Units)))
183 return TRUE;
188 return FALSE;
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);
213 return TRUE;
216 static const ULONG rx_tags[] = {
217 S2_CopyToBuff,
218 S2_CopyToBuff16
221 static const ULONG tx_tags[] = {
222 S2_CopyFromBuff,
223 S2_CopyFromBuff16,
224 S2_CopyFromBuff32
227 static int GM_UNIQUENAME(Open)
229 LIBBASETYPEPTR LIBBASE,
230 struct IOSana2Req* req,
231 ULONG unitnum,
232 ULONG flags
235 struct TagItem *tags;
236 struct e1000Unit *unit = NULL, *unit_current;
237 struct Opener *opener;
238 BYTE error=0;
239 int i;
241 if (!(IsListEmpty(&LIBBASE->e1kb_Units)))
243 ForeachNode(&LIBBASE->e1kb_Units, unit_current)
245 if (unit_current->e1ku_UnitNum == unitnum)
246 unit = unit_current;
250 D(bug("[e1000] OpenDevice(%d)\n", unitnum));
252 if (unit != NULL)
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 */
267 if(error == 0)
269 if(unit->e1ku_open_count != 0 && ((unit->e1ku_ifflags & IFF_SHARED) == 0 ||
270 (flags & SANA2OPF_MINE) != 0))
272 error = IOERR_UNITBUSY;
274 else
276 unit->e1ku_open_count++;
280 if(error == 0)
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;
291 if(opener == NULL)
292 error = IOERR_OPENFAIL;
295 if(error == 0)
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);
308 Disable();
309 AddTail((APTR)&unit->e1ku_Openers, (APTR)opener);
310 Enable();
313 if (error != 0)
314 CloseDevice((struct IORequest *)req);
315 else
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;
326 else
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);
357 if (error == 0)
358 e1000func_configure(unit);
360 if ((error == 0) && (request_irq(unit)))
362 error = IOERR_OPENFAIL;
364 else
366 D(bug("[%s] OpenDevice: IRQ Attached\n", unit->e1ku_name));
370 else
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 */
393 // unit->stop(unit);
394 (void)unit;
396 opener = (APTR)req->ios2_BufferManagement;
397 if ((APTR)req->ios2_BufferManagement != NULL)
399 Disable();
400 Remove((struct Node *)opener);
401 Enable();
402 FreeVec(opener);
405 return TRUE;
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)
418 AROS_LIBFUNC_INIT
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);
433 else
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);
440 AROS_LIBFUNC_EXIT
443 AROS_LH1(LONG, abortio,
444 AROS_LHA(struct IOSana2Req *, req, A1),
445 LIBBASETYPEPTR, LIBBASE, 6, e1000)
447 AROS_LIBFUNC_INIT
448 struct e1000Unit *unit;
450 D(bug("[e1000] AbortIO()\n"));
452 if ((unit = (APTR)req->ios2_Req.io_Unit) != NULL)
454 Disable();
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);
463 Enable();
466 return 0;
468 AROS_LIBFUNC_EXIT