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,
24 #include <exec/types.h>
25 #include <exec/resident.h>
27 #include <exec/errors.h>
28 #include <exec/lists.h>
30 #include <aros/libcall.h>
31 #include <aros/symbolsets.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>
44 #include <proto/oop.h>
45 #include <proto/exec.h>
46 #include <proto/utility.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
))
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";
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";
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
);
140 D(bug("[rtl8139] PCI_Enumerator: Failed to create unit!\n"));
143 RTLD(bug("[%s] PCI_Enumerator: %s NIC I/O MEM @ %08x\n", unit
->rtl8139u_name
, unit
->rtl8139u_rtl_chipname
, unit
->rtl8139u_BaseMem
))
150 static int GM_UNIQUENAME(Init
)(LIBBASETYPEPTR LIBBASE
)
152 D(bug("[rtl8139] Init()\n"));
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
));
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
,
183 HIDD_PCI_EnumDevices( LIBBASE
->rtl8139b_PCI
,
188 if (!(IsListEmpty(&LIBBASE
->rtl8139b_Units
)))
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
);
226 static const ULONG rx_tags
[] =
232 static const ULONG tx_tags
[] =
239 static int GM_UNIQUENAME(Open
)
241 LIBBASETYPEPTR LIBBASE
,
242 struct IOSana2Req
* req
,
247 struct TagItem
*tags
;
248 struct RTL8139Unit
*unit
= NULL
, *unit_current
;
249 struct Opener
*opener
;
253 if (!(IsListEmpty(&LIBBASE
->rtl8139b_Units
)))
255 ForeachNode(&LIBBASE
->rtl8139b_Units
, unit_current
)
257 if (unit_current
->rtl8139u_UnitNum
== unitnum
)
264 D(bug("[rtl8139] OpenDevice(%d)\n", unitnum
));
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 */
283 req
->ios2_Req
.io_Unit
= (APTR
)unit
;
286 /* Handle device sharing */
289 if (unit
->rtl8139u_open_count
!= 0 && ((unit
->rtl8139u_flags
& IFF_SHARED
) == 0 ||
290 (flags
& SANA2OPF_MINE
) != 0))
292 error
= IOERR_UNITBUSY
;
296 unit
->rtl8139u_open_count
++;
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
;
317 error
= IOERR_OPENFAIL
;
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
);
339 AddTail((APTR
)&unit
->rtl8139u_Openers
, (APTR
)opener
);
344 CloseDevice((struct IORequest
*)req
);
345 else if (unit
->rtl8139u_open_count
== 1)
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
;
374 Remove((struct Node
*)opener
);
379 if (--unit
->rtl8139u_open_count
== 0)
382 /* Without this, DHCP doesn't work the second time the device is used */
383 ((struct Library
*)LIBBASE
)->lib_Flags
|= LIBF_DELEXP
;
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
)
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
);
412 req
->ios2_Req
.io_Flags
&= ~IOF_QUICK
;
413 PutMsg(unit
->rtl8139u_input_port
, (struct Message
*)req
);
419 AROS_LH1(LONG
, AbortIO
,
420 AROS_LHA(struct IOSana2Req
*, req
, A1
),
421 LIBBASETYPEPTR
, LIBBASE
, 6, RTL8139Dev
)
424 struct RTL8139Unit
*unit
;
425 unit
= (APTR
)req
->ios2_Req
.io_Unit
;
427 RTLD(bug("[rtl8139] AbortIO()\n"))
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
);