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,
22 #include <exec/types.h>
23 #include <exec/resident.h>
25 #include <exec/errors.h>
26 #include <exec/lists.h>
28 #include <aros/libcall.h>
29 #include <aros/symbolsets.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>
42 #include <proto/oop.h>
43 #include <proto/exec.h>
44 #include <proto/utility.h>
50 #include LC_LIBDEFS_FILE
52 AROS_UFH3(void, PCI_Enumerator
,
53 AROS_UFHA(struct Hook
*, hook
, A0
),
54 AROS_UFHA(OOP_Object
*, pciDevice
, A2
),
55 AROS_UFHA(APTR
, message
, A1
))
59 D(bug("[SiS900] PCI_Enumerator()\n"));
61 LIBBASETYPEPTR LIBBASE
= (LIBBASETYPEPTR
)hook
->h_Data
;
63 BOOL FoundCompatNIC
= FALSE
;
64 IPTR DeviceID
, VendorID
, RevisionID
;
65 char *CardName
, *CardChipName
;
66 struct SiS900Unit
*unit
;
68 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_VendorID
, &VendorID
);
69 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_ProductID
, &DeviceID
);
70 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_RevisionID
, &RevisionID
);
72 if ((DeviceID
== 0x0900))
74 FoundCompatNIC
= TRUE
;
75 CardName
= "SiS 900 PCI Fast Ethernet";
76 CardChipName
= "SiS900";
78 else if ((DeviceID
== 0x7016))
80 FoundCompatNIC
= TRUE
;
81 CardName
= "SiS 7016 PCI Fast Ethernet";
82 CardChipName
= "SiS7016";
87 D(bug("[SiS900] PCI_Enumerator: Found %s NIC, PCI_ID %04x:%04x Rev:%d\n", CardName
, VendorID
, DeviceID
, RevisionID
));
89 if ((unit
= CreateUnit(LIBBASE
, pciDevice
, CardName
, CardChipName
)))
91 AddTail(&LIBBASE
->sis900b_Units
, (struct Node
*)&unit
->sis900u_Node
);
95 D(bug("[SIS900] PCI_Enumerator: Failed to create unit!\n"));
99 D(bug("[%s] PCI_Enumerator: %s NIC I/O MEM @ %08x\n", unit
->sis900u_name
, unit
->sis900u_rtl_chipname
, unit
->sis900u_BaseMem
));
105 static int GM_UNIQUENAME(Init
)(LIBBASETYPEPTR LIBBASE
)
107 D(bug("[SiS900] Init()\n"));
110 sprintf((char *)tmpbuff
, SiS900_TASK_NAME
, "sis900.0");
112 if (FindTask(tmpbuff
) != NULL
)
114 D(bug("[SiS900] device already up and running.\n"));
118 NEWLIST(&LIBBASE
->sis900b_Units
);
120 LIBBASE
->sis900b_PCIDeviceAttrBase
= OOP_ObtainAttrBase(IID_Hidd_PCIDevice
);
122 if (LIBBASE
->sis900b_PCIDeviceAttrBase
!= 0)
124 D(bug("[SiS900] HiddPCIDeviceAttrBase @ %p\n", LIBBASE
->sis900b_PCIDeviceAttrBase
));
126 LIBBASE
->sis900b_PCI
= OOP_NewObject(NULL
, CLID_Hidd_PCI
, NULL
);
128 if (LIBBASE
->sis900b_PCI
)
130 D(bug("[SiS900] PCI Subsystem HIDD object @ %p\n", LIBBASE
->sis900b_PCI
));
132 struct Hook FindHook
= {
133 h_Entry
: (IPTR (*)())PCI_Enumerator
,
137 struct TagItem Requirements
[] = {
138 { tHidd_PCI_VendorID
, 0x1039 },
142 HIDD_PCI_EnumDevices(LIBBASE
->sis900b_PCI
,
144 (struct TagItem
*)&Requirements
147 if (!(IsListEmpty(&LIBBASE
->sis900b_Units
)))
157 static int GM_UNIQUENAME(Expunge
)(LIBBASETYPEPTR LIBBASE
)
159 D(bug("[SiS900] Expunge()\n"));
161 struct SiS900Unit
*unit_current
, *unit_tmp
;
163 if (!(IsListEmpty(&LIBBASE
->sis900b_Units
)))
165 ForeachNodeSafe(&LIBBASE
->sis900b_Units
, unit_current
, unit_tmp
)
167 DeleteUnit(LIBBASE
, unit_current
);
171 if (LIBBASE
->sis900b_PCIDeviceAttrBase
!= 0)
172 OOP_ReleaseAttrBase(IID_Hidd_PCIDevice
);
174 LIBBASE
->sis900b_PCIDeviceAttrBase
= 0;
176 if (LIBBASE
->sis900b_PCI
!= NULL
)
177 OOP_DisposeObject(LIBBASE
->sis900b_PCI
);
182 static const ULONG rx_tags
[] = {
187 static const ULONG tx_tags
[] = {
194 * Open device handles currently only one sis900 unit.
196 static int GM_UNIQUENAME(Open
)
198 LIBBASETYPEPTR LIBBASE
,
199 struct IOSana2Req
* req
,
204 struct TagItem
*tags
;
205 struct SiS900Unit
*unit
= NULL
, *unit_current
;
206 struct Opener
*opener
;
210 if (!(IsListEmpty(&LIBBASE
->sis900b_Units
)))
212 ForeachNode(&LIBBASE
->sis900b_Units
, unit_current
)
214 if (unit_current
->sis900u_UnitNum
== unitnum
)
219 D(bug("[SiS900] OpenDevice(%d)\n", unitnum
));
223 D(bug("[SiS900] OpenDevice: Unit %d @ %p\n", unitnum
, unit
));
224 req
->ios2_Req
.io_Unit
= NULL
;
225 tags
= req
->ios2_BufferManagement
;
227 req
->ios2_BufferManagement
= NULL
;
229 /* Check request size */
230 if (req
->ios2_Req
.io_Message
.mn_Length
< sizeof(struct IOSana2Req
))
231 error
= IOERR_OPENFAIL
;
233 /* Get the requested unit */
236 req
->ios2_Req
.io_Unit
= (APTR
)unit
;
239 /* Handle device sharing */
242 if(unit
->sis900u_open_count
!= 0 && ((unit
->sis900u_ifflags
& IFF_SHARED
) == 0 ||
243 (flags
& SANA2OPF_MINE
) != 0))
244 error
= IOERR_UNITBUSY
;
245 unit
->sis900u_open_count
++;
250 if((flags
& SANA2OPF_MINE
) == 0)
251 unit
->sis900u_ifflags
|= IFF_SHARED
;
252 else if((flags
& SANA2OPF_PROM
) != 0)
253 unit
->sis900u_ifflags
|= IFF_PROMISC
;
255 /* Set up buffer-management structure and get hooks */
256 opener
= AllocVec(sizeof(struct Opener
), MEMF_PUBLIC
| MEMF_CLEAR
);
257 req
->ios2_BufferManagement
= (APTR
)opener
;
260 error
= IOERR_OPENFAIL
;
265 NEWLIST(&opener
->read_port
.mp_MsgList
);
266 opener
->read_port
.mp_Flags
= PA_IGNORE
;
267 NEWLIST((APTR
)&opener
->initial_stats
);
269 for(i
= 0; i
< 2; i
++)
270 opener
->rx_function
= (APTR
)GetTagData(rx_tags
[i
], (IPTR
)opener
->rx_function
, tags
);
271 for(i
= 0; i
< 3; i
++)
272 opener
->tx_function
= (APTR
)GetTagData(tx_tags
[i
], (IPTR
)opener
->tx_function
, tags
);
274 opener
->filter_hook
= (APTR
)GetTagData(S2_PacketFilter
, 0, tags
);
277 AddTail((APTR
)&unit
->sis900u_Openers
, (APTR
)opener
);
282 CloseDevice((struct IORequest
*)req
);
284 sis900func_open(unit
);
289 D(bug("[SiS900] OpenDevice: Invalid Unit! (unitno = %d)\n", unitnum
));
290 error
= IOERR_OPENFAIL
;
293 req
->ios2_Req
.io_Error
= error
;
295 return (error
!=0) ? FALSE
: TRUE
;
298 static int GM_UNIQUENAME(Close
)
300 LIBBASETYPEPTR LIBBASE
,
301 struct IOSana2Req
* req
304 struct SiS900Unit
*unit
= (struct SiS900Unit
*)req
->ios2_Req
.io_Unit
;
305 struct Opener
*opener
;
307 D(bug("[SiS900] CloseDevice(unit @ %p, unitno %d)\n", unit
, unit
->sis900u_UnitNum
));
309 sis900func_close(unit
);
311 opener
= (APTR
)req
->ios2_BufferManagement
;
315 Remove((struct Node
*)opener
);
324 ADD2INITLIB(GM_UNIQUENAME(Init
),0)
325 ADD2EXPUNGELIB(GM_UNIQUENAME(Expunge
),0)
326 ADD2OPENDEV(GM_UNIQUENAME(Open
),0)
327 ADD2CLOSEDEV(GM_UNIQUENAME(Close
),0)
329 AROS_LH1(void, beginio
,
330 AROS_LHA(struct IOSana2Req
*, req
, A1
),
331 LIBBASETYPEPTR
, LIBBASE
, 5, SiS900Dev
)
334 struct SiS900Unit
*unit
;
336 D(bug("[SiS900] BeginIO()\n"));
338 req
->ios2_Req
.io_Error
= 0;
339 unit
= (APTR
)req
->ios2_Req
.io_Unit
;
341 if (AttemptSemaphore(&unit
->sis900u_unit_lock
))
343 handle_request(LIBBASE
, req
);
347 req
->ios2_Req
.io_Flags
&= ~IOF_QUICK
;
348 PutMsg(unit
->sis900u_input_port
, (struct Message
*)req
);
354 AROS_LH1(LONG
, abortio
,
355 AROS_LHA(struct IOSana2Req
*, req
, A1
),
356 LIBBASETYPEPTR
, LIBBASE
, 6, SiS900Dev
)
360 D(bug("[SiS900] AbortIO()\n"));
363 if ((req
->ios2_Req
.io_Message
.mn_Node
.ln_Type
== NT_MESSAGE
) &&
364 (req
->ios2_Req
.io_Flags
& IOF_QUICK
) == 0)
366 Remove((struct Node
*)req
);
367 req
->ios2_Req
.io_Error
= IOERR_ABORTED
;
368 req
->ios2_WireError
= S2WERR_GENERIC_ERROR
;
369 ReplyMsg((struct Message
*)req
);