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
))
60 struct RTL8169Unit
*unit
= NULL
;
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"));
82 D(bug("[rtl8169] PCI_Enumerator: Max supported units already reached\n"));
85 RTLD(bug("[%s] PCI_Enumerator: %s MMIO @ %p\n", unit
->rtl8169u_name
, unit
->rtl8169u_rtl_chipname
, unit
->rtl8169u_BaseMem
))
90 static int GM_UNIQUENAME(Init
)(LIBBASETYPEPTR LIBBASE
)
92 D(bug("[rtl8169] Init()\n"));
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
));
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 },
139 struct Hook FindHook
=
141 h_Entry
: (IPTR (*)()) PCI_Enumerator
,
145 struct pHidd_PCI_EnumDevices enummsg
=
147 mID
: OOP_GetMethodID(IID_Hidd_PCI
, moHidd_PCI_EnumDevices
),
149 requirements
: (struct TagItem
*) &Requirements
,
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
);
164 if (!(IsListEmpty(&LIBBASE
->rtl8169b_Units
)))
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
);
202 static const ULONG rx_tags
[] = {
208 static const ULONG tx_tags
[] =
215 static int GM_UNIQUENAME(Open
)
217 LIBBASETYPEPTR LIBBASE
,
218 struct IOSana2Req
* req
,
223 struct TagItem
*tags
;
224 struct RTL8169Unit
*unit
= NULL
, *unit_current
;
225 struct Opener
*opener
;
229 if (!(IsListEmpty(&LIBBASE
->rtl8169b_Units
)))
231 ForeachNode(&LIBBASE
->rtl8169b_Units
, unit_current
)
233 if (unit_current
->rtl8169u_UnitNum
== unitnum
)
240 D(bug("[rtl8169] OpenDevice(%d)\n", unitnum
));
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 */
260 req
->ios2_Req
.io_Unit
= (APTR
)unit
;
263 /* Handle device sharing */
266 if ((unit
->rtl8169u_open_count
!= 0) &&
267 ((unit
->rtl8169u_flags
& IFF_SHARED
) == 0 ||
268 (flags
& SANA2OPF_MINE
) != 0))
270 error
= IOERR_UNITBUSY
;
274 unit
->rtl8169u_open_count
++;
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
;
290 error
= IOERR_OPENFAIL
;
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
);
313 AddTail((APTR
) &unit
->rtl8169u_Openers
, (APTR
) opener
);
319 CloseDevice((struct IORequest
*)req
);
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)
353 opener
= (APTR
)req
->ios2_BufferManagement
;
357 Remove((struct Node
*)opener
);
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
)
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
);
388 req
->ios2_Req
.io_Flags
&= ~IOF_QUICK
;
389 PutMsg(unit
->rtl8169u_input_port
, (struct Message
*)req
);
394 D(bug("[rtl8169] BeginIO: Called with unit == NULL\n"));
400 AROS_LH1(LONG
, AbortIO
,
401 AROS_LHA(struct IOSana2Req
*, req
, A1
),
402 LIBBASETYPEPTR
, LIBBASE
, 6, RTL8169Dev
)
405 struct RTL8169Unit
*unit
;
407 D(bug("[rtl8169] AbortIO()\n"));
409 if ((unit
= (struct RTL8169Unit
*)req
->ios2_Req
.io_Unit
) != NULL
)
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
);