revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / networks / rtl8169 / rtl8169_init.c
blob3f63ae44efc34613f49134a3acd8dbae8c345f4f
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 "rtl8169.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 struct RTL8169Unit *unit = NULL;
61 IPTR RevisionID;
63 D(bug("[rtl8169] PCI_Enumerator(PCI Device Obj @ %p)\n", pciDevice));
65 LIBBASETYPEPTR LIBBASE = (LIBBASETYPEPTR) hook->h_Data;
67 OOP_GetAttr(pciDevice, aHidd_PCIDevice_RevisionID, &RevisionID);
69 D(bug("[rtl8169] PCI_Enumerator: Found RTL8169 Rev:%d\n", RevisionID));
71 if ((LIBBASE->rtl8169b_UnitCount < MAX_UNITS) && ((unit = CreateUnit(LIBBASE, pciDevice, RevisionID)) != NULL))
73 AddTail(&LIBBASE->rtl8169b_Units, (struct Node *)&unit->rtl8169u_Node);
75 else if (LIBBASE->rtl8169b_UnitCount < MAX_UNITS)
77 D(bug("[rtl8169] PCI_Enumerator: Failed to create unit!\n"));
78 return;
80 else
82 D(bug("[rtl8169] PCI_Enumerator: Max supported units already reached\n"));
83 return;
85 RTLD(bug("[%s] PCI_Enumerator: %s MMIO @ %p\n", unit->rtl8169u_name, unit->rtl8169u_rtl_chipname, unit->rtl8169u_BaseMem))
87 AROS_USERFUNC_EXIT
90 static int GM_UNIQUENAME(Init)(LIBBASETYPEPTR LIBBASE)
92 D(bug("[rtl8169] Init()\n"));
94 UBYTE tmpbuff[100];
95 int i;
97 sprintf((char *) tmpbuff, RTL8169_TASK_NAME, "rtl8169.0");
99 if (FindTask(tmpbuff) != NULL)
101 D(bug("[rtl8169] Init: Found Task '%s'! - Device already up and running.\n", tmpbuff));
102 return FALSE;
105 /* Load config options */
106 LIBBASE->rtl8169b_MaxIntWork = 20;
107 LIBBASE->rtl8169b_MulticastFilterLimit = 32;
109 for (i = 0; i < MAX_UNITS; i++)
111 LIBBASE->speed[i] = -1;
112 LIBBASE->duplex[i] = -1;
113 LIBBASE->autoneg[i] = -1;
116 NEWLIST(&LIBBASE->rtl8169b_Units);
118 LIBBASE->rtl8169b_PCIDeviceAttrBase = OOP_ObtainAttrBase(IID_Hidd_PCIDevice);
120 if (LIBBASE->rtl8169b_PCIDeviceAttrBase != 0)
122 D(bug("[rtl8169] Init: HiddPCIDeviceAttrBase @ %p\n", LIBBASE->rtl8169b_PCIDeviceAttrBase));
124 LIBBASE->rtl8169b_PCI = OOP_NewObject(NULL, CLID_Hidd_PCI, NULL);
126 if (LIBBASE->rtl8169b_PCI)
128 D(bug("[rtl8169] Init: PCI Subsystem HIDD object @ %p\n", LIBBASE->rtl8169b_PCI));
130 struct TagItem Requirements[] =
132 { tHidd_PCI_VendorID, 0 },
133 { tHidd_PCI_ProductID, 0 },
134 { tHidd_PCI_SubsystemVendorID, 0 },
135 { tHidd_PCI_SubsystemID, 0 },
136 { TAG_DONE, 0 }
139 struct Hook FindHook =
141 h_Entry: (IPTR (*)()) PCI_Enumerator,
142 h_Data: LIBBASE,
145 struct pHidd_PCI_EnumDevices enummsg =
147 mID: OOP_GetMethodID(IID_Hidd_PCI, moHidd_PCI_EnumDevices),
148 callback: &FindHook,
149 requirements: (struct TagItem *) &Requirements,
150 }, *msg = &enummsg;
152 i = 0;
153 // Browse all known cards
154 while(cards[i].vendorID)
156 Requirements[0].ti_Data = cards[i].vendorID;
157 Requirements[1].ti_Data = cards[i].productID;
158 Requirements[2].ti_Data = cards[i].sub_vendorID;
159 Requirements[3].ti_Data = cards[i].sub_productID;
160 OOP_DoMethod(LIBBASE->rtl8169b_PCI, (OOP_Msg) msg);
161 i++;
164 if (!(IsListEmpty(&LIBBASE->rtl8169b_Units)))
166 return TRUE;
170 return FALSE;
173 static int GM_UNIQUENAME(Expunge)(LIBBASETYPEPTR LIBBASE)
175 D(bug("[rtl8169] Expunge()\n"));
177 struct RTL8169Unit *unit_current, *unit_tmp;
179 if (!(IsListEmpty(&LIBBASE->rtl8169b_Units)))
181 ForeachNodeSafe(&LIBBASE->rtl8169b_Units, unit_current, unit_tmp)
183 DeleteUnit(LIBBASE, unit_current);
187 if (LIBBASE->rtl8169b_PCIDeviceAttrBase != 0)
189 OOP_ReleaseAttrBase(IID_Hidd_PCIDevice);
192 LIBBASE->rtl8169b_PCIDeviceAttrBase = 0;
194 if (LIBBASE->rtl8169b_PCI != NULL)
196 OOP_DisposeObject(LIBBASE->rtl8169b_PCI);
199 return TRUE;
202 static const ULONG rx_tags[] = {
203 S2_CopyToBuff,
204 S2_CopyToBuff16,
205 S2_CopyToBuff32
208 static const ULONG tx_tags[] =
210 S2_CopyFromBuff,
211 S2_CopyFromBuff16,
212 S2_CopyFromBuff32
215 static int GM_UNIQUENAME(Open)
217 LIBBASETYPEPTR LIBBASE,
218 struct IOSana2Req* req,
219 ULONG unitnum,
220 ULONG flags
223 struct TagItem *tags;
224 struct RTL8169Unit *unit = NULL, *unit_current;
225 struct Opener *opener;
226 BYTE error=0;
227 int i;
229 if (!(IsListEmpty(&LIBBASE->rtl8169b_Units)))
231 ForeachNode(&LIBBASE->rtl8169b_Units, unit_current)
233 if (unit_current->rtl8169u_UnitNum == unitnum)
235 unit = unit_current;
240 D(bug("[rtl8169] OpenDevice(%d)\n", unitnum));
242 if (unit != NULL)
244 RTLD(bug("[%s] OpenDevice: Unit %d @ %p\n", unit->rtl8169u_name, unitnum, unit))
246 req->ios2_Req.io_Unit = NULL;
247 tags = req->ios2_BufferManagement;
249 req->ios2_BufferManagement = NULL;
251 /* Check request size */
252 if (req->ios2_Req.io_Message.mn_Length < sizeof(struct IOSana2Req))
254 error = IOERR_OPENFAIL;
257 /* Get the requested unit */
258 if (error == 0)
260 req->ios2_Req.io_Unit = (APTR)unit;
263 /* Handle device sharing */
264 if (error == 0)
266 if ((unit->rtl8169u_open_count != 0) &&
267 ((unit->rtl8169u_flags & IFF_SHARED) == 0 ||
268 (flags & SANA2OPF_MINE) != 0))
270 error = IOERR_UNITBUSY;
272 else
274 unit->rtl8169u_open_count++;
278 if (error == 0)
280 if ((flags & SANA2OPF_MINE) == 0)
281 unit->rtl8169u_flags |= IFF_SHARED;
282 else if ((flags & SANA2OPF_PROM) != 0)
283 unit->rtl8169u_flags |= IFF_PROMISC;
285 /* Set up buffer-management structure and get hooks */
286 opener = AllocVec(sizeof(struct Opener), MEMF_PUBLIC | MEMF_CLEAR);
287 req->ios2_BufferManagement = (APTR)opener;
289 if(opener == NULL)
290 error = IOERR_OPENFAIL;
293 if (error == 0)
295 NEWLIST(&opener->read_port.mp_MsgList);
296 opener->read_port.mp_Flags = PA_IGNORE;
297 NEWLIST((APTR)&opener->initial_stats);
299 for (i = 0; i < 2; i++)
301 opener->rx_function = (APTR) GetTagData(rx_tags[i],
302 (IPTR) opener->rx_function, tags);
304 for (i = 0; i < 3; i++)
306 opener->tx_function = (APTR) GetTagData(tx_tags[i],
307 (IPTR) opener->tx_function, tags);
310 opener->filter_hook = (APTR) GetTagData(S2_PacketFilter, 0, tags);
312 Disable();
313 AddTail((APTR) &unit->rtl8169u_Openers, (APTR) opener);
314 Enable();
317 if (error != 0)
319 CloseDevice((struct IORequest *)req);
321 else
323 unit->start(unit);
326 else
328 D(bug("[rtl8169] OpenDevice: Invalid Unit! (unitno = %d)\n", unitnum));
329 error = IOERR_OPENFAIL;
332 req->ios2_Req.io_Error = error;
334 return (error != 0) ? FALSE : TRUE;
337 static int GM_UNIQUENAME(Close)
339 LIBBASETYPEPTR LIBBASE,
340 struct IOSana2Req* req
343 struct RTL8169Unit *unit = (struct RTL8169Unit *) req->ios2_Req.io_Unit;
344 struct Opener *opener;
346 if ((unit = (struct RTL8169Unit *) req->ios2_Req.io_Unit) != NULL)
348 RTLD(bug("[rtl8169] CloseDevice(unit @ %p, unitno %d)\n", unit, unit->rtl8169u_UnitNum))
350 if((unit->rtl8169u_flags & IFF_UP) != 0)
351 unit->stop(unit);
353 opener = (APTR)req->ios2_BufferManagement;
354 if (opener != NULL)
356 Disable();
357 Remove((struct Node *)opener);
358 Enable();
359 FreeVec(opener);
362 return TRUE;
365 ADD2INITLIB(GM_UNIQUENAME(Init), 0)
366 ADD2EXPUNGELIB(GM_UNIQUENAME(Expunge), 0)
367 ADD2OPENDEV(GM_UNIQUENAME(Open), 0)
368 ADD2CLOSEDEV(GM_UNIQUENAME(Close), 0)
370 AROS_LH1(void, BeginIO,
371 AROS_LHA(struct IOSana2Req *, req, A1),
372 LIBBASETYPEPTR, LIBBASE, 5, RTL8169Dev)
374 AROS_LIBFUNC_INIT
375 struct RTL8169Unit *unit;
377 D(bug("[rtl8169] BeginIO()\n"));
379 req->ios2_Req.io_Error = 0;
380 if ((unit = (struct RTL8169Unit *) req->ios2_Req.io_Unit) != NULL)
382 if (AttemptSemaphore(&unit->rtl8169u_unit_lock))
384 handle_request(LIBBASE, req);
386 else
388 req->ios2_Req.io_Flags &= ~IOF_QUICK;
389 PutMsg(unit->rtl8169u_input_port, (struct Message *)req);
392 else
394 D(bug("[rtl8169] BeginIO: Called with unit == NULL\n"));
397 AROS_LIBFUNC_EXIT
400 AROS_LH1(LONG, AbortIO,
401 AROS_LHA(struct IOSana2Req *, req, A1),
402 LIBBASETYPEPTR, LIBBASE, 6, RTL8169Dev)
404 AROS_LIBFUNC_INIT
405 struct RTL8169Unit *unit;
407 D(bug("[rtl8169] AbortIO()\n"));
409 if ((unit = (struct RTL8169Unit *)req->ios2_Req.io_Unit) != NULL)
411 Disable();
412 if ((req->ios2_Req.io_Message.mn_Node.ln_Type == NT_MESSAGE) &&
413 (req->ios2_Req.io_Flags & IOF_QUICK) == 0)
415 Remove((struct Node *)req);
416 req->ios2_Req.io_Error = IOERR_ABORTED;
417 req->ios2_WireError = S2WERR_GENERIC_ERROR;
418 ReplyMsg((struct Message *)req);
420 Enable();
422 return 0;
424 AROS_LIBFUNC_EXIT