grub2: bring back build of aros-side grub2 tools
[AROS.git] / workbench / devs / networks / rtl8139 / rtl8139_init.c
blob5d62dbc32127bf74d673af47f305a2fed9cd3e88
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 "rtl8139.h"
24 #include <exec/types.h>
25 #include <exec/resident.h>
26 #include <exec/io.h>
27 #include <exec/errors.h>
28 #include <exec/lists.h>
30 #include <aros/libcall.h>
31 #include <aros/symbolsets.h>
33 #include <oop/oop.h>
35 #include <devices/sana2.h>
36 #include <devices/sana2specialstats.h>
38 #include <utility/utility.h>
39 #include <utility/tagitem.h>
40 #include <utility/hooks.h>
42 #include <hidd/pci.h>
44 #include <proto/oop.h>
45 #include <proto/exec.h>
46 #include <proto/utility.h>
48 #include <stdio.h>
50 #include "unit.h"
51 #include LC_LIBDEFS_FILE
53 AROS_UFH3(void, PCI_Enumerator,
54 AROS_UFHA(struct Hook *, hook, A0),
55 AROS_UFHA(OOP_Object *, pciDevice, A2),
56 AROS_UFHA(APTR, message, A1))
58 AROS_USERFUNC_INIT
60 char *CardName,
61 *CardChipName;
62 IPTR DeviceID,
63 VendorID,
64 RevisionID,
65 CardCapabilities;
66 BOOL FoundCompatNIC = FALSE;
68 D(bug("[rtl8139] PCI_Enumerator(PCI Device Obj @ %p)\n", pciDevice));
70 LIBBASETYPEPTR LIBBASE = (LIBBASETYPEPTR)hook->h_Data;
72 OOP_GetAttr(pciDevice, aHidd_PCIDevice_VendorID, &VendorID);
73 OOP_GetAttr(pciDevice, aHidd_PCIDevice_ProductID, &DeviceID);
74 OOP_GetAttr(pciDevice, aHidd_PCIDevice_RevisionID, &RevisionID);
76 if ((VendorID == 0x10ec) && (DeviceID == 0x8129))
78 FoundCompatNIC = TRUE;
79 CardCapabilities = RTLc_HAS_MII_XCVR;
80 CardName = "RealTek RTL8129";
81 CardChipName = "RTL8129";
83 else if ((VendorID == 0x10ec) && ((DeviceID == 0x8138) || (DeviceID == 0x8139)))
85 FoundCompatNIC = TRUE;
86 if ((DeviceID == 0x8139) && (RevisionID >= 0x20))
88 CardCapabilities = RTLc_HAS_CHIP_XCVR | RTLc_HAS_LNK_CHNG | RTLc_HAS_DESC;
89 CardName = "RealTek RTL8139D";
90 CardChipName = "RTL8139D";
92 else
94 CardCapabilities = RTLc_HAS_CHIP_XCVR | RTLc_HAS_LNK_CHNG;
95 CardName = "RealTek RTL8139C";
96 CardChipName = "RTL8139C";
99 else if ((VendorID == 0x1113) && (DeviceID == 0x1211))
101 FoundCompatNIC = TRUE;
102 CardCapabilities = RTLc_HAS_CHIP_XCVR | RTLc_HAS_LNK_CHNG;
103 CardName = "Accton EN-1207D Fast Ethernet";
104 CardChipName = "RTL8139";
106 else if ((VendorID == 0x1186) && (DeviceID == 0x1300))
108 FoundCompatNIC = TRUE;
109 CardCapabilities = RTLc_HAS_CHIP_XCVR | RTLc_HAS_LNK_CHNG;
110 CardName = "D-Link DFE-538TX";
111 CardChipName = "RTL8139";
113 else if ((VendorID == 0x018a) && (DeviceID == 0x0106))
115 FoundCompatNIC = TRUE;
116 CardCapabilities = RTLc_HAS_CHIP_XCVR | RTLc_HAS_LNK_CHNG;
117 CardName = "LevelOne FPC-0106Tx";
118 CardChipName = "RTL8139";
120 else if ((VendorID == 0x021b) && (DeviceID == 0x8139))
122 FoundCompatNIC = TRUE;
123 CardCapabilities = RTLc_HAS_CHIP_XCVR | RTLc_HAS_LNK_CHNG;
124 CardName = "Compaq HNE-300";
125 CardChipName = "RTL8139";
128 if (FoundCompatNIC)
130 D(bug("[rtl8139] PCI_Enumerator: Found %s NIC [%s], PCI_ID %04x:%04x Rev:%d\n", CardName, CardChipName, VendorID, DeviceID, RevisionID));
132 struct RTL8139Unit *unit = NULL;
134 if ((unit = CreateUnit(LIBBASE, pciDevice, CardCapabilities, CardName, CardChipName)) != NULL)
136 AddTail(&LIBBASE->rtl8139b_Units, (struct Node *)&unit->rtl8139u_Node);
138 else
140 D(bug("[rtl8139] PCI_Enumerator: Failed to create unit!\n"));
141 return;
143 RTLD(bug("[%s] PCI_Enumerator: %s NIC I/O MEM @ %08x\n", unit->rtl8139u_name, unit->rtl8139u_rtl_chipname, unit->rtl8139u_BaseMem))
147 AROS_USERFUNC_EXIT
150 static int GM_UNIQUENAME(Init)(LIBBASETYPEPTR LIBBASE)
152 D(bug("[rtl8139] Init()\n"));
154 UBYTE tmpbuff[100];
155 sprintf((char *)tmpbuff, RTL8139_TASK_NAME, "rtl8139.0");
157 if (FindTask(tmpbuff) != NULL)
159 D(bug("[rtl8139] Init: Found Task '%s'! - Device already up and running.\n", tmpbuff));
160 return FALSE;
163 NEWLIST(&LIBBASE->rtl8139b_Units);
165 LIBBASE->rtl8139b_PCIDeviceAttrBase = OOP_ObtainAttrBase(IID_Hidd_PCIDevice);
167 if (LIBBASE->rtl8139b_PCIDeviceAttrBase != 0)
169 D(bug("[rtl8139] Init: HiddPCIDeviceAttrBase @ %p\n", LIBBASE->rtl8139b_PCIDeviceAttrBase));
171 LIBBASE->rtl8139b_PCI = OOP_NewObject(NULL, CLID_Hidd_PCI, NULL);
173 if (LIBBASE->rtl8139b_PCI)
175 D(bug("[rtl8139] Init: PCI Subsystem HIDD object @ %p\n", LIBBASE->rtl8139b_PCI));
177 struct Hook FindHook =
179 h_Entry: (IPTR (*)())PCI_Enumerator,
180 h_Data: LIBBASE,
183 HIDD_PCI_EnumDevices( LIBBASE->rtl8139b_PCI,
184 &FindHook,
185 NULL
188 if (!(IsListEmpty(&LIBBASE->rtl8139b_Units)))
190 return TRUE;
194 return FALSE;
197 static int GM_UNIQUENAME(Expunge)(LIBBASETYPEPTR LIBBASE)
199 D(bug("[rtl8139] Expunge()\n"));
201 struct RTL8139Unit *unit_current, *unit_tmp;
203 if (!(IsListEmpty(&LIBBASE->rtl8139b_Units)))
205 ForeachNodeSafe(&LIBBASE->rtl8139b_Units, unit_current, unit_tmp)
207 DeleteUnit(LIBBASE, unit_current);
211 if (LIBBASE->rtl8139b_PCIDeviceAttrBase != 0)
213 OOP_ReleaseAttrBase(IID_Hidd_PCIDevice);
216 LIBBASE->rtl8139b_PCIDeviceAttrBase = 0;
218 if (LIBBASE->rtl8139b_PCI != NULL)
220 OOP_DisposeObject(LIBBASE->rtl8139b_PCI);
223 return TRUE;
226 static const ULONG rx_tags[] =
228 S2_CopyToBuff,
229 S2_CopyToBuff16
232 static const ULONG tx_tags[] =
234 S2_CopyFromBuff,
235 S2_CopyFromBuff16,
236 S2_CopyFromBuff32
239 static int GM_UNIQUENAME(Open)
241 LIBBASETYPEPTR LIBBASE,
242 struct IOSana2Req* req,
243 ULONG unitnum,
244 ULONG flags
247 struct TagItem *tags;
248 struct RTL8139Unit *unit = NULL, *unit_current;
249 struct Opener *opener;
250 BYTE error=0;
251 int i;
253 if (!(IsListEmpty(&LIBBASE->rtl8139b_Units)))
255 ForeachNode(&LIBBASE->rtl8139b_Units, unit_current)
257 if (unit_current->rtl8139u_UnitNum == unitnum)
259 unit = unit_current;
264 D(bug("[rtl8139] OpenDevice(%d)\n", unitnum));
266 if (unit != NULL)
268 RTLD(bug("[rtl8139] OpenDevice: Unit %d @ %p\n", unitnum, unit));
269 req->ios2_Req.io_Unit = NULL;
270 tags = req->ios2_BufferManagement;
272 req->ios2_BufferManagement = NULL;
274 /* Check request size */
275 if (req->ios2_Req.io_Message.mn_Length < sizeof(struct IOSana2Req))
277 error = IOERR_OPENFAIL;
280 /* Get the requested unit */
281 if (error == 0)
283 req->ios2_Req.io_Unit = (APTR)unit;
286 /* Handle device sharing */
287 if (error == 0)
289 if (unit->rtl8139u_open_count != 0 && ((unit->rtl8139u_flags & IFF_SHARED) == 0 ||
290 (flags & SANA2OPF_MINE) != 0))
292 error = IOERR_UNITBUSY;
294 else
296 unit->rtl8139u_open_count++;
300 if (error == 0)
302 if ((flags & SANA2OPF_MINE) == 0)
304 unit->rtl8139u_flags |= IFF_SHARED;
306 else if ((flags & SANA2OPF_PROM) != 0)
308 unit->rtl8139u_flags |= IFF_PROMISC;
311 /* Set up buffer-management structure and get hooks */
312 opener = AllocVec(sizeof(struct Opener), MEMF_PUBLIC | MEMF_CLEAR);
313 req->ios2_BufferManagement = (APTR)opener;
315 if(opener == NULL)
317 error = IOERR_OPENFAIL;
321 if (error == 0)
323 NEWLIST(&opener->read_port.mp_MsgList);
324 opener->read_port.mp_Flags = PA_IGNORE;
325 NEWLIST((APTR)&opener->initial_stats);
327 for (i = 0; i < 2; i++)
329 opener->rx_function = (APTR)GetTagData(rx_tags[i], (IPTR)opener->rx_function, tags);
331 for (i = 0; i < 3; i++)
333 opener->tx_function = (APTR)GetTagData(tx_tags[i], (IPTR)opener->tx_function, tags);
336 opener->filter_hook = (APTR)GetTagData(S2_PacketFilter, 0, tags);
338 Disable();
339 AddTail((APTR)&unit->rtl8139u_Openers, (APTR)opener);
340 Enable();
343 if (error != 0)
344 CloseDevice((struct IORequest *)req);
345 else if (unit->rtl8139u_open_count == 1)
346 unit->start(unit);
348 else
350 D(bug("[rtl8139] OpenDevice: Invalid Unit! (unitno = %d)\n", unitnum));
351 error = IOERR_OPENFAIL;
354 req->ios2_Req.io_Error = error;
356 return (error !=0) ? FALSE : TRUE;
359 static int GM_UNIQUENAME(Close)
361 LIBBASETYPEPTR LIBBASE,
362 struct IOSana2Req* req
365 struct RTL8139Unit *unit = (struct RTL8139Unit *)req->ios2_Req.io_Unit;
366 struct Opener *opener;
368 RTLD(bug("[rtl8139] CloseDevice(unit @ %p, unitno %d)\n", unit, unit->rtl8139u_UnitNum));
370 opener = (APTR)req->ios2_BufferManagement;
371 if (opener != NULL)
373 Disable();
374 Remove((struct Node *)opener);
375 Enable();
376 FreeVec(opener);
379 if (--unit->rtl8139u_open_count == 0)
380 unit->stop(unit);
382 /* Without this, DHCP doesn't work the second time the device is used */
383 ((struct Library *)LIBBASE)->lib_Flags |= LIBF_DELEXP;
385 return TRUE;
389 ADD2INITLIB(GM_UNIQUENAME(Init),0)
390 ADD2EXPUNGELIB(GM_UNIQUENAME(Expunge),0)
391 ADD2OPENDEV(GM_UNIQUENAME(Open),0)
392 ADD2CLOSEDEV(GM_UNIQUENAME(Close),0)
394 AROS_LH1(void, BeginIO,
395 AROS_LHA(struct IOSana2Req *, req, A1),
396 LIBBASETYPEPTR, LIBBASE, 5, RTL8139Dev)
398 AROS_LIBFUNC_INIT
399 struct RTL8139Unit *unit;
401 req->ios2_Req.io_Error = 0;
402 unit = (APTR)req->ios2_Req.io_Unit;
404 RTLD(bug("[rtl8139] BeginIO()\n"));
406 if (AttemptSemaphore(&unit->rtl8139u_unit_lock))
408 handle_request(LIBBASE, req);
410 else
412 req->ios2_Req.io_Flags &= ~IOF_QUICK;
413 PutMsg(unit->rtl8139u_input_port, (struct Message *)req);
416 AROS_LIBFUNC_EXIT
419 AROS_LH1(LONG, AbortIO,
420 AROS_LHA(struct IOSana2Req *, req, A1),
421 LIBBASETYPEPTR, LIBBASE, 6, RTL8139Dev)
423 AROS_LIBFUNC_INIT
424 struct RTL8139Unit *unit;
425 unit = (APTR)req->ios2_Req.io_Unit;
427 RTLD(bug("[rtl8139] AbortIO()\n"))
429 Disable();
430 if ((req->ios2_Req.io_Message.mn_Node.ln_Type == NT_MESSAGE) &&
431 (req->ios2_Req.io_Flags & IOF_QUICK) == 0)
433 Remove((struct Node *)req);
434 req->ios2_Req.io_Error = IOERR_ABORTED;
435 req->ios2_WireError = S2WERR_GENERIC_ERROR;
436 ReplyMsg((struct Message *)req);
438 Enable();
440 return 0;
442 AROS_LIBFUNC_EXIT