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/debug.h>
32 #include <aros/symbolsets.h>
36 #include <devices/sana2.h>
37 #include <devices/sana2specialstats.h>
39 #include <utility/utility.h>
40 #include <utility/tagitem.h>
41 #include <utility/hooks.h>
45 #include <proto/oop.h>
46 #include <proto/exec.h>
47 #include <proto/utility.h>
51 #include LC_LIBDEFS_FILE
53 AROS_UFH3(void, Enumerator
,
54 AROS_UFHA(struct Hook
*, hook
, A0
),
55 AROS_UFHA(OOP_Object
*, pciDevice
, A2
),
56 AROS_UFHA(APTR
, message
, A1
))
60 LIBBASETYPEPTR LIBBASE
= (LIBBASETYPEPTR
)hook
->h_Data
;
63 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_ProductID
, &DeviceID
);
65 if ((DeviceID
== NFORCE_MCPNET1_ID
) ||
66 (DeviceID
== NFORCE_MCPNET2_ID
) ||
67 (DeviceID
== NFORCE_MCPNET3_ID
) ||
68 (DeviceID
== NFORCE_MCPNET4_ID
) ||
69 (DeviceID
== NFORCE_MCPNET5_ID
) ||
70 (DeviceID
== NFORCE_MCPNET6_ID
) ||
71 (DeviceID
== NFORCE_MCPNET7_ID
) ||
72 (DeviceID
== NFORCE_MCPNET8_ID
) ||
73 (DeviceID
== NFORCE_MCPNET9_ID
) ||
74 (DeviceID
== NFORCE_MCPNET10_ID
) ||
75 (DeviceID
== NFORCE_MCPNET11_ID
))
77 struct NFUnit
*unit
= CreateUnit(LIBBASE
, pciDevice
);
78 LIBBASE
->nf_unit
= unit
;
80 D(bug("[nforce] Found nForce NIC, ProductID = %04x\n", DeviceID
));
81 D(bug("[nforce] nForce NIC I/O @ %08x\n", unit
->nu_BaseIO
));
82 D(bug("[nforce] nForce NIC MEM @ %08x\n", unit
->nu_BaseMem
));
88 static int GM_UNIQUENAME(Init
)(LIBBASETYPEPTR LIBBASE
)
90 D(bug("[nforce] Init()\n"));
92 if (FindTask(NFORCE_TASK_NAME
) != NULL
)
94 D(bug("[nforce] device already up and running.\n"));
98 LIBBASE
->nf_Sana2Info
.HardwareType
= S2WireType_Ethernet
;
99 LIBBASE
->nf_Sana2Info
.MTU
= ETH_MTU
;
100 LIBBASE
->nf_Sana2Info
.AddrFieldSize
= 8 * ETH_ADDRESSSIZE
;
102 LIBBASE
->nf_pciDeviceAttrBase
= OOP_ObtainAttrBase(IID_Hidd_PCIDevice
);
104 if (LIBBASE
->nf_pciDeviceAttrBase
!= 0)
106 D(bug("[nforce] Got HiddPCIDeviceAttrBase\n"));
108 LIBBASE
->nf_pci
= OOP_NewObject(NULL
, CLID_Hidd_PCI
, NULL
);
112 D(bug("[nforce] Got PCI object\n"));
114 struct Hook FindHook
= {
115 h_Entry
: (IPTR (*)())Enumerator
,
119 struct TagItem Requirements
[] = {
120 { tHidd_PCI_VendorID
, 0x10de },
124 HIDD_PCI_EnumDevices( LIBBASE
->nf_pci
,
126 (struct TagItem
*)&Requirements
129 if (LIBBASE
->nf_unit
)
139 static int GM_UNIQUENAME(Expunge
)(LIBBASETYPEPTR LIBBASE
)
141 D(bug("[nforce] Expunge\n"));
143 if (LIBBASE
->nf_unit
)
145 DeleteUnit(LIBBASE
, LIBBASE
->nf_unit
);
146 LIBBASE
->nf_unit
= NULL
;
149 if (LIBBASE
->nf_pciDeviceAttrBase
!= 0)
150 OOP_ReleaseAttrBase(IID_Hidd_PCIDevice
);
152 LIBBASE
->nf_pciDeviceAttrBase
= 0;
154 if (LIBBASE
->nf_pci
!= NULL
)
155 OOP_DisposeObject(LIBBASE
->nf_pci
);
160 static const ULONG rx_tags
[] = {
165 static const ULONG tx_tags
[] = {
172 * Open device handles currently only one nforce unit.
174 * It could change in future if only multiple phy support works in forcedeth.c
177 static int GM_UNIQUENAME(Open
)
179 LIBBASETYPEPTR LIBBASE
,
180 struct IOSana2Req
*req
,
185 struct TagItem
*tags
;
186 struct NFUnit
*unit
= LIBBASE
->nf_unit
;
187 struct Opener
*opener
;
191 D(bug("[nforce] OpenDevice\n"));
193 LIBBASE
->nf_Device
.dd_Library
.lib_OpenCnt
++;
194 LIBBASE
->nf_Device
.dd_Library
.lib_Flags
&= ~LIBF_DELEXP
;
196 req
->ios2_Req
.io_Unit
= NULL
;
197 tags
= req
->ios2_BufferManagement
;
199 req
->ios2_BufferManagement
= NULL
;
201 /* Check request size */
203 if(req
->ios2_Req
.io_Message
.mn_Length
< sizeof(struct IOSana2Req
))
204 error
= IOERR_OPENFAIL
;
206 /* Get the requested unit */
207 if((error
== 0) && (unitnum
== 0))
209 req
->ios2_Req
.io_Unit
= (APTR
)unit
;
211 else error
= IOERR_OPENFAIL
;
213 /* Handle device sharing */
217 if(unit
->open_count
!= 0 && ((unit
->flags
& IFF_SHARED
) == 0 ||
218 (flags
& SANA2OPF_MINE
) != 0))
219 error
= IOERR_UNITBUSY
;
225 if((flags
& SANA2OPF_MINE
) == 0)
226 unit
->flags
|= IFF_SHARED
;
227 else if((flags
& SANA2OPF_PROM
) != 0)
228 unit
->flags
|= IFF_PROMISC
;
230 /* Set up buffer-management structure and get hooks */
231 opener
= AllocVec(sizeof(struct Opener
), MEMF_PUBLIC
| MEMF_CLEAR
);
232 req
->ios2_BufferManagement
= (APTR
)opener
;
235 error
= IOERR_OPENFAIL
;
240 NEWLIST(&opener
->read_port
.mp_MsgList
);
241 opener
->read_port
.mp_Flags
= PA_IGNORE
;
242 NEWLIST((APTR
)&opener
->initial_stats
);
244 for(i
= 0; i
< 2; i
++)
245 opener
->rx_function
= (APTR
)GetTagData(rx_tags
[i
], (IPTR
)opener
->rx_function
, tags
);
246 for(i
= 0; i
< 3; i
++)
247 opener
->tx_function
= (APTR
)GetTagData(tx_tags
[i
], (IPTR
)opener
->tx_function
, tags
);
249 opener
->filter_hook
= (APTR
)GetTagData(S2_PacketFilter
, 0, tags
);
252 AddTail((APTR
)&unit
->nu_Openers
, (APTR
)opener
);
257 CloseDevice((struct IORequest
*)req
);
261 req
->ios2_Req
.io_Error
= error
;
263 return (error
!=0) ? FALSE
: TRUE
;
266 static int GM_UNIQUENAME(Close
)
268 LIBBASETYPEPTR LIBBASE
,
269 struct IOSana2Req
*req
272 struct NFUnit
*unit
= LIBBASE
->nf_unit
;
273 struct Opener
*opener
;
275 D(bug("[nforce] CloseDevice\n"));
279 opener
= (APTR
)req
->ios2_BufferManagement
;
283 Remove((struct Node
*)opener
);
292 ADD2INITLIB(GM_UNIQUENAME(Init
),0)
293 ADD2EXPUNGELIB(GM_UNIQUENAME(Expunge
),0)
294 ADD2OPENDEV(GM_UNIQUENAME(Open
),0)
295 ADD2CLOSEDEV(GM_UNIQUENAME(Close
),0)
297 AROS_LH1(void, beginio
,
298 AROS_LHA(struct IOSana2Req
*, req
, A1
),
299 LIBBASETYPEPTR
, LIBBASE
, 5, Nforce
)
304 D(bug("[nforce] BeginIO\n"));
306 req
->ios2_Req
.io_Error
= 0;
307 dev
= (APTR
)req
->ios2_Req
.io_Unit
;
309 if (AttemptSemaphore(&dev
->unit_lock
))
311 handle_request(LIBBASE
, req
);
315 req
->ios2_Req
.io_Flags
&= ~IOF_QUICK
;
316 PutMsg(dev
->nu_input_port
, (struct Message
*)req
);
322 AROS_LH1(LONG
, abortio
,
323 AROS_LHA(struct IOSana2Req
*, req
, A1
),
324 LIBBASETYPEPTR
, LIBBASE
, 6, Nforce
)
328 D(bug("[nforce] AbortIO\n"));
331 if ((req
->ios2_Req
.io_Message
.mn_Node
.ln_Type
== NT_MESSAGE
) &&
332 (req
->ios2_Req
.io_Flags
& IOF_QUICK
) == 0)
334 Remove((struct Node
*)req
);
335 req
->ios2_Req
.io_Error
= IOERR_ABORTED
;
336 req
->ios2_WireError
= S2WERR_GENERIC_ERROR
;
337 ReplyMsg((struct Message
*)req
);