Fixed binary search: no more infinite loops when vendor is unknown.
[tangerine.git] / workbench / devs / networks / rtl8139 / rtl8139_init.c
blob3c1ce0b629fb52ee5ef8221340f446e6406cc82e
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 RTL8139C";
90 CardChipName = "RTL8139C";
92 else
94 CardCapabilities = RTLc_HAS_CHIP_XCVR | RTLc_HAS_LNK_CHNG;
95 CardName = "RealTek RTL8139";
96 CardChipName = "RTL8139";
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 == 0x018a) && (DeviceID == 0x0106))
122 FoundCompatNIC = TRUE;
123 CardCapabilities = RTLc_HAS_CHIP_XCVR | RTLc_HAS_LNK_CHNG;
124 CardName = "Compaq HNE-300";
125 CardChipName = "RTL8139c";
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, &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 = {
178 h_Entry: (IPTR (*)())PCI_Enumerator,
179 h_Data: LIBBASE,
182 HIDD_PCI_EnumDevices( LIBBASE->rtl8139b_PCI,
183 &FindHook,
184 NULL
187 if (!(IsListEmpty(&LIBBASE->rtl8139b_Units)))
189 return TRUE;
193 return FALSE;
196 static int GM_UNIQUENAME(Expunge)(LIBBASETYPEPTR LIBBASE)
198 D(bug("[rtl8139] Expunge()\n"));
200 struct RTL8139Unit *unit_current, *unit_tmp;
202 if (!(IsListEmpty(&LIBBASE->rtl8139b_Units)))
204 ForeachNodeSafe(&LIBBASE->rtl8139b_Units, unit_current, unit_tmp)
206 DeleteUnit(LIBBASE, unit_current);
210 if (LIBBASE->rtl8139b_PCIDeviceAttrBase != 0)
211 OOP_ReleaseAttrBase(IID_Hidd_PCIDevice);
213 LIBBASE->rtl8139b_PCIDeviceAttrBase = 0;
215 if (LIBBASE->rtl8139b_PCI != NULL)
216 OOP_DisposeObject(LIBBASE->rtl8139b_PCI);
218 return TRUE;
221 static const ULONG rx_tags[] = {
222 S2_CopyToBuff,
223 S2_CopyToBuff16
226 static const ULONG tx_tags[] = {
227 S2_CopyFromBuff,
228 S2_CopyFromBuff16,
229 S2_CopyFromBuff32
232 static int GM_UNIQUENAME(Open)
234 LIBBASETYPEPTR LIBBASE,
235 struct IOSana2Req* req,
236 ULONG unitnum,
237 ULONG flags
240 struct TagItem *tags;
241 struct RTL8139Unit *unit = NULL, *unit_current;
242 struct Opener *opener;
243 BYTE error=0;
244 int i;
246 if (!(IsListEmpty(&LIBBASE->rtl8139b_Units)))
248 ForeachNode(&LIBBASE->rtl8139b_Units, unit_current)
250 if (unit_current->rtl8139u_UnitNum == unitnum)
251 unit = unit_current;
255 D(bug("[rtl8139] OpenDevice(%d)\n", unitnum));
257 if (unit != NULL)
259 RTLD(bug("[rtl8139] OpenDevice: Unit %d @ %p\n", unitnum, unit));
260 req->ios2_Req.io_Unit = NULL;
261 tags = req->ios2_BufferManagement;
263 req->ios2_BufferManagement = NULL;
265 /* Check request size */
266 if (req->ios2_Req.io_Message.mn_Length < sizeof(struct IOSana2Req))
267 error = IOERR_OPENFAIL;
269 /* Get the requested unit */
270 if (error == 0)
271 req->ios2_Req.io_Unit = (APTR)unit;
273 /* Handle device sharing */
274 if (error == 0)
276 if (unit->rtl8139u_open_count != 0 && ((unit->rtl8139u_flags & IFF_SHARED) == 0 ||
277 (flags & SANA2OPF_MINE) != 0))
278 error = IOERR_UNITBUSY;
279 else
280 unit->rtl8139u_open_count++;
283 if (error == 0)
285 if ((flags & SANA2OPF_MINE) == 0)
286 unit->rtl8139u_flags |= IFF_SHARED;
287 else if ((flags & SANA2OPF_PROM) != 0)
288 unit->rtl8139u_flags |= IFF_PROMISC;
290 /* Set up buffer-management structure and get hooks */
291 opener = AllocVec(sizeof(struct Opener), MEMF_PUBLIC | MEMF_CLEAR);
292 req->ios2_BufferManagement = (APTR)opener;
294 if(opener == NULL)
295 error = IOERR_OPENFAIL;
298 if (error == 0)
300 NEWLIST(&opener->read_port.mp_MsgList);
301 opener->read_port.mp_Flags = PA_IGNORE;
302 NEWLIST((APTR)&opener->initial_stats);
304 for (i = 0; i < 2; i++)
305 opener->rx_function = (APTR)GetTagData(rx_tags[i], (IPTR)opener->rx_function, tags);
306 for (i = 0; i < 3; i++)
307 opener->tx_function = (APTR)GetTagData(tx_tags[i], (IPTR)opener->tx_function, tags);
309 opener->filter_hook = (APTR)GetTagData(S2_PacketFilter, 0, tags);
311 Disable();
312 AddTail((APTR)&unit->rtl8139u_Openers, (APTR)opener);
313 Enable();
316 if (error != 0)
317 CloseDevice((struct IORequest *)req);
318 else
319 unit->start(unit);
321 else
323 D(bug("[rtl8139] OpenDevice: Invalid Unit! (unitno = %d)\n", unitnum));
324 error = IOERR_OPENFAIL;
327 req->ios2_Req.io_Error = error;
329 return (error !=0) ? FALSE : TRUE;
332 static int GM_UNIQUENAME(Close)
334 LIBBASETYPEPTR LIBBASE,
335 struct IOSana2Req* req
338 struct RTL8139Unit *unit = (struct RTL8139Unit *)req->ios2_Req.io_Unit;
339 struct Opener *opener;
341 RTLD(bug("[rtl8139] CloseDevice(unit @ %p, unitno %d)\n", unit, unit->rtl8139u_UnitNum))
343 unit->stop(unit);
345 opener = (APTR)req->ios2_BufferManagement;
346 if (opener != NULL)
348 Disable();
349 Remove((struct Node *)opener);
350 Enable();
351 FreeVec(opener);
354 return TRUE;
358 ADD2INITLIB(GM_UNIQUENAME(Init),0)
359 ADD2EXPUNGELIB(GM_UNIQUENAME(Expunge),0)
360 ADD2OPENDEV(GM_UNIQUENAME(Open),0)
361 ADD2CLOSEDEV(GM_UNIQUENAME(Close),0)
363 AROS_LH1(void, BeginIO,
364 AROS_LHA(struct IOSana2Req *, req, A1),
365 LIBBASETYPEPTR, LIBBASE, 5, RTL8139Dev)
367 AROS_LIBFUNC_INIT
368 struct RTL8139Unit *unit;
370 RTLD(bug("[rtl8139] BeginIO()\n"));
372 req->ios2_Req.io_Error = 0;
373 unit = (APTR)req->ios2_Req.io_Unit;
375 if (AttemptSemaphore(&unit->rtl8139u_unit_lock))
377 handle_request(LIBBASE, req);
379 else
381 req->ios2_Req.io_Flags &= ~IOF_QUICK;
382 PutMsg(unit->rtl8139u_input_port, (struct Message *)req);
385 AROS_LIBFUNC_EXIT
388 AROS_LH1(LONG, AbortIO,
389 AROS_LHA(struct IOSana2Req *, req, A1),
390 LIBBASETYPEPTR, LIBBASE, 6, RTL8139Dev)
392 AROS_LIBFUNC_INIT
393 struct RTL8139Unit *unit;
394 unit = (APTR)req->ios2_Req.io_Unit;
396 RTLD(bug("[rtl8139] AbortIO()\n"))
398 Disable();
399 if ((req->ios2_Req.io_Message.mn_Node.ln_Type == NT_MESSAGE) &&
400 (req->ios2_Req.io_Flags & IOF_QUICK) == 0)
402 Remove((struct Node *)req);
403 req->ios2_Req.io_Error = IOERR_ABORTED;
404 req->ios2_WireError = S2WERR_GENERIC_ERROR;
405 ReplyMsg((struct Message *)req);
407 Enable();
409 return 0;
411 AROS_LIBFUNC_EXIT