revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / networks / pcnet32 / pcnet32_init.c
blobde200a6382d942a9b4d3adcb96bf1819cda08d81
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 <exec/types.h>
23 #include <exec/resident.h>
24 #include <exec/io.h>
25 #include <exec/errors.h>
26 #include <exec/lists.h>
28 #include <aros/libcall.h>
29 #include <aros/symbolsets.h>
31 #include <oop/oop.h>
33 #include <devices/sana2.h>
34 #include <devices/sana2specialstats.h>
36 #include <utility/utility.h>
37 #include <utility/tagitem.h>
38 #include <utility/hooks.h>
40 #include <hidd/pci.h>
42 #include <proto/oop.h>
43 #include <proto/exec.h>
44 #include <proto/utility.h>
46 #include "pcnet32.h"
47 #include "unit.h"
48 #include LC_LIBDEFS_FILE
50 AROS_UFH3(void, Enumerator,
51 AROS_UFHA(struct Hook *, hook, A0),
52 AROS_UFHA(OOP_Object *, pciDevice, A2),
53 AROS_UFHA(APTR, message, A1))
55 AROS_USERFUNC_INIT
57 D(bug("[pcnet32] init.PCI_Enumerator()\n"));
59 LIBBASETYPEPTR LIBBASE = (LIBBASETYPEPTR)hook->h_Data;
61 IPTR DeviceID;
62 OOP_GetAttr(pciDevice, aHidd_PCIDevice_ProductID, &DeviceID);
64 if ((DeviceID == 0x2000) ||
65 (DeviceID == 0x2001) ||
66 (DeviceID == 0x2625))
68 D(bug("[pcnet32] Found PCNet32 NIC, ProductID = %04x\n", DeviceID));
70 struct PCN32Unit *unit = CreateUnit(LIBBASE, pciDevice);
71 LIBBASE->pcnb_unit = unit;
73 D(bug("[pcnet32] PCNet32 NIC I/O MEM @ %08x\n", unit->pcnu_BaseMem));
76 AROS_USERFUNC_EXIT
79 static int GM_UNIQUENAME(Init)(LIBBASETYPEPTR LIBBASE)
81 D(bug("[pcnet32] init.Init()\n"));
83 if (FindTask(PCNET32_TASK_NAME) != NULL)
85 D(bug("[pcnet32] device already up and running.\n"));
86 return FALSE;
89 LIBBASE->pcnb_Sana2Info.HardwareType = S2WireType_Ethernet;
90 LIBBASE->pcnb_Sana2Info.MTU = ETH_MTU;
91 LIBBASE->pcnb_Sana2Info.AddrFieldSize = 8 * ETH_ADDRESSSIZE;
93 LIBBASE->pcnb_pciDeviceAttrBase = OOP_ObtainAttrBase(IID_Hidd_PCIDevice);
95 if (LIBBASE->pcnb_pciDeviceAttrBase != 0)
97 D(bug("[pcnet32] Got HiddPCIDeviceAttrBase\n"));
99 LIBBASE->pcnb_pci = OOP_NewObject(NULL, CLID_Hidd_PCI, NULL);
101 if (LIBBASE->pcnb_pci)
103 D(bug("[pcnet32] Got PCI object\n"));
105 struct Hook FindHook = {
106 h_Entry: (IPTR (*)())Enumerator,
107 h_Data: LIBBASE,
110 struct TagItem Requirements[] = {
111 { tHidd_PCI_VendorID, 0x1022 },
112 { TAG_DONE, 0UL }
115 HIDD_PCI_EnumDevices( LIBBASE->pcnb_pci,
116 &FindHook,
117 (struct TagItem *)&Requirements
120 if (LIBBASE->pcnb_unit)
122 return TRUE;
127 return FALSE;
130 static int GM_UNIQUENAME(Expunge)(LIBBASETYPEPTR LIBBASE)
132 D(bug("[pcnet32] init.Expunge\n"));
134 if (LIBBASE->pcnb_unit)
136 DeleteUnit(LIBBASE, LIBBASE->pcnb_unit);
137 LIBBASE->pcnb_unit = NULL;
140 if (LIBBASE->pcnb_pciDeviceAttrBase != 0)
141 OOP_ReleaseAttrBase(IID_Hidd_PCIDevice);
143 LIBBASE->pcnb_pciDeviceAttrBase = 0;
145 if (LIBBASE->pcnb_pci != NULL)
146 OOP_DisposeObject(LIBBASE->pcnb_pci);
148 return TRUE;
151 static const ULONG rx_tags[] = {
152 S2_CopyToBuff,
153 S2_CopyToBuff16
156 static const ULONG tx_tags[] = {
157 S2_CopyFromBuff,
158 S2_CopyFromBuff16,
159 S2_CopyFromBuff32
163 * Open device handles currently only one pcnet32 unit.
165 static int GM_UNIQUENAME(Open)
167 LIBBASETYPEPTR LIBBASE,
168 struct IOSana2Req* req,
169 ULONG unitnum,
170 ULONG flags
173 struct TagItem *tags;
174 struct PCN32Unit *unit = LIBBASE->pcnb_unit;
175 struct Opener *opener;
176 BYTE error=0;
177 int i;
179 D(bug("[pcnet32] init.OpenDevice\n"));
181 req->ios2_Req.io_Unit = NULL;
182 tags = req->ios2_BufferManagement;
184 req->ios2_BufferManagement = NULL;
186 /* Check request size */
188 if(req->ios2_Req.io_Message.mn_Length < sizeof(struct IOSana2Req))
189 error = IOERR_OPENFAIL;
191 /* Get the requested unit */
192 if((error == 0) && (unitnum == 0))
194 req->ios2_Req.io_Unit = (APTR)unit;
196 else error = IOERR_OPENFAIL;
198 /* Handle device sharing */
200 if(error == 0)
202 if(unit->pcnu_open_count != 0 && ((unit->pcnu_flags & IFF_SHARED) == 0 ||
203 (flags & SANA2OPF_MINE) != 0))
204 error = IOERR_UNITBUSY;
205 unit->pcnu_open_count++;
208 if(error == 0)
210 if((flags & SANA2OPF_MINE) == 0)
211 unit->pcnu_flags |= IFF_SHARED;
212 else if((flags & SANA2OPF_PROM) != 0)
213 unit->pcnu_flags |= IFF_PROMISC;
215 /* Set up buffer-management structure and get hooks */
216 opener = AllocVec(sizeof(struct Opener), MEMF_PUBLIC | MEMF_CLEAR);
217 req->ios2_BufferManagement = (APTR)opener;
219 if(opener == NULL)
220 error = IOERR_OPENFAIL;
223 if(error == 0)
225 NEWLIST(&opener->read_port.mp_MsgList);
226 opener->read_port.mp_Flags = PA_IGNORE;
227 NEWLIST((APTR)&opener->initial_stats);
229 for(i = 0; i < 2; i++)
230 opener->rx_function = (APTR)GetTagData(rx_tags[i], (IPTR)opener->rx_function, tags);
231 for(i = 0; i < 3; i++)
232 opener->tx_function = (APTR)GetTagData(tx_tags[i], (IPTR)opener->tx_function, tags);
234 opener->filter_hook = (APTR)GetTagData(S2_PacketFilter, 0, tags);
236 Disable();
237 AddTail((APTR)&unit->pcnu_Openers, (APTR)opener);
238 Enable();
241 if (error != 0)
242 CloseDevice((struct IORequest *)req);
243 else
244 unit->start(unit);
246 req->ios2_Req.io_Error = error;
248 return (error !=0) ? FALSE : TRUE;
251 static int GM_UNIQUENAME(Close)
253 LIBBASETYPEPTR LIBBASE,
254 struct IOSana2Req* req
257 struct PCN32Unit *unit = LIBBASE->pcnb_unit;
258 struct Opener *opener;
260 D(bug("[pcnet32] init.CloseDevice\n"));
262 if((unit->pcnu_flags & IFF_UP) != 0)
263 unit->stop(unit);
265 opener = (APTR)req->ios2_BufferManagement;
266 if (opener != NULL)
268 Disable();
269 Remove((struct Node *)opener);
270 Enable();
271 FreeVec(opener);
274 /* Without this, DHCP doesn't work the second time the device is used */
275 ((struct Library *)LIBBASE)->lib_Flags |= LIBF_DELEXP;
277 return TRUE;
281 ADD2INITLIB(GM_UNIQUENAME(Init),0)
282 ADD2EXPUNGELIB(GM_UNIQUENAME(Expunge),0)
283 ADD2OPENDEV(GM_UNIQUENAME(Open),0)
284 ADD2CLOSEDEV(GM_UNIQUENAME(Close),0)
286 AROS_LH1(void, beginio,
287 AROS_LHA(struct IOSana2Req *, req, A1),
288 LIBBASETYPEPTR, LIBBASE, 5, PCNet32)
290 AROS_LIBFUNC_INIT
291 struct PCN32Unit *dev;
293 D(bug("[pcnet32] init.BeginIO\n"));
295 req->ios2_Req.io_Error = 0;
296 dev = (APTR)req->ios2_Req.io_Unit;
298 if (AttemptSemaphore(&dev->pcnu_unit_lock))
300 handle_request(LIBBASE, req);
302 else
304 req->ios2_Req.io_Flags &= ~IOF_QUICK;
305 PutMsg(dev->pcnu_input_port, (struct Message *)req);
308 AROS_LIBFUNC_EXIT
311 AROS_LH1(LONG, abortio,
312 AROS_LHA(struct IOSana2Req *, req, A1),
313 LIBBASETYPEPTR, LIBBASE, 6, PCNet32)
315 AROS_LIBFUNC_INIT
317 D(bug("[pcnet32] init.AbortIO\n"));
319 Disable();
320 if ((req->ios2_Req.io_Message.mn_Node.ln_Type == NT_MESSAGE) &&
321 (req->ios2_Req.io_Flags & IOF_QUICK) == 0)
323 Remove((struct Node *)req);
324 req->ios2_Req.io_Error = IOERR_ABORTED;
325 req->ios2_WireError = S2WERR_GENERIC_ERROR;
326 ReplyMsg((struct Message *)req);
328 Enable();
330 return 0;
332 AROS_LIBFUNC_EXIT