4 * Created on: May 14, 2009
9 #include <aros/debug.h>
10 #include <aros/libcall.h>
11 #include <aros/symbolsets.h>
13 #include <exec/memory.h>
15 #include <exec/errors.h>
16 #include <exec/devices.h>
17 #include <exec/ports.h>
19 #include <utility/tagitem.h>
21 #include <devices/sana2.h>
22 #include <devices/sana2specialstats.h>
24 #include <proto/openfirmware.h>
25 #include <proto/exec.h>
26 #include <proto/utility.h>
32 #include LC_LIBDEFS_FILE
43 static int FEC_Init(struct FECBase
*FECBase
)
46 void *OpenFirmwareBase
= NULL
;
49 D(bug("[FEC] Fast Ethernet Controller Init.\n"));
51 OpenFirmwareBase
= OpenResource("openfirmware.resource");
57 key
= OF_OpenKey("/builtin/ethernet");
61 prop
= OF_FindProperty(key
, "reg");
65 reg_t
*reg
= OF_GetPropValue(prop
);
66 fec
= (fec_t
*)reg
->addr
;
68 D(bug("[FEC] FEC registers at %08x\n", fec
));
70 prop
= OF_FindProperty(key
, "mac-address");
74 FECBase
->feb_Pool
= CreatePool(MEMF_CLEAR
| MEMF_PUBLIC
| MEMF_SEM_PROTECTED
, 8192, 4096);
76 if (FECBase
->feb_Pool
)
78 if (FEC_CreateUnit(FECBase
, fec
))
80 mac_addr_t
*mac
= OF_GetPropValue(prop
);
81 D(bug("[FEC] MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
82 mac
->b
[0], mac
->b
[1], mac
->b
[2], mac
->b
[3], mac
->b
[4], mac
->b
[5]));
84 FECBase
->feb_Unit
->feu_OrgAddr
[0] = mac
->b
[0];
85 FECBase
->feb_Unit
->feu_OrgAddr
[1] = mac
->b
[1];
86 FECBase
->feb_Unit
->feu_OrgAddr
[2] = mac
->b
[2];
87 FECBase
->feb_Unit
->feu_OrgAddr
[3] = mac
->b
[3];
88 FECBase
->feb_Unit
->feu_OrgAddr
[4] = mac
->b
[4];
89 FECBase
->feb_Unit
->feu_OrgAddr
[5] = mac
->b
[5];
95 D(bug("[FEC] Failed to create the unit\n"));
97 DeletePool(FECBase
->feb_Pool
);
106 bug("[FEC] OpenFirmware not found. Aborting.\n");
113 static const uintptr_t rx_tags
[] = {
118 static const uintptr_t tx_tags
[] = {
125 * Open device handles currently only one pcnet32 unit.
127 static int FEC_Open(struct FECBase
*FECBase
, struct IOSana2Req
* req
, ULONG unitnum
, ULONG flags
)
129 struct TagItem
*tags
;
130 struct FECUnit
*unit
= NULL
;
131 struct Opener
*opener
;
135 D(bug("[FEC] OpenDevice(%d)\n", unitnum
));
137 req
->ios2_Req
.io_Unit
= NULL
;
138 tags
= req
->ios2_BufferManagement
;
140 req
->ios2_BufferManagement
= NULL
;
142 /* Check request size */
144 if(req
->ios2_Req
.io_Message
.mn_Length
< sizeof(struct IOSana2Req
))
145 error
= IOERR_OPENFAIL
;
147 if ((error
!= 0) || (unitnum
> 1))
149 error
= IOERR_OPENFAIL
;
153 unit
= FECBase
->feb_Unit
;
154 req
->ios2_Req
.io_Unit
= &unit
->feu_Unit
;
157 /* Handle device sharing */
160 if(unit
->feu_OpenCount
!= 0 && ((unit
->feu_Flags
& IFF_SHARED
) == 0 ||
161 (flags
& SANA2OPF_MINE
) != 0))
162 error
= IOERR_UNITBUSY
;
164 unit
->feu_OpenCount
++;
169 if((flags
& SANA2OPF_MINE
) == 0)
170 unit
->feu_Flags
|= IFF_SHARED
;
171 else if((flags
& SANA2OPF_PROM
) != 0)
172 unit
->feu_Flags
|= IFF_PROMISC
;
174 /* Set up buffer-management structure and get hooks */
175 opener
= AllocVecPooled(FECBase
->feb_Pool
, sizeof(struct Opener
));
176 req
->ios2_BufferManagement
= (APTR
)opener
;
179 error
= IOERR_OPENFAIL
;
184 NEWLIST(&opener
->read_port
.mp_MsgList
);
185 opener
->read_port
.mp_Flags
= PA_IGNORE
;
186 NEWLIST((APTR
)&opener
->initial_stats
);
188 for(i
= 0; i
< 2; i
++)
189 opener
->rx_function
= (APTR
)GetTagData(rx_tags
[i
], (IPTR
)opener
->rx_function
, tags
);
190 for(i
= 0; i
< 3; i
++)
191 opener
->tx_function
= (APTR
)GetTagData(tx_tags
[i
], (IPTR
)opener
->tx_function
, tags
);
193 opener
->filter_hook
= (APTR
)GetTagData(S2_PacketFilter
, 0, tags
);
196 AddTail((APTR
)&unit
->feu_Openers
, (APTR
)opener
);
201 CloseDevice((struct IORequest
*)req
);
205 req
->ios2_Req
.io_Error
= error
;
206 return (error
!=0) ? FALSE
: TRUE
;
209 static int FEC_Close(struct FECBase
*FECBase
, struct IOSana2Req
* req
)
211 struct FECUnit
*unit
= (struct FECUnit
*)req
->ios2_Req
.io_Unit
;
212 struct Opener
*opener
;
216 D(bug("[FEC] CloseDevice\n"));
220 opener
= (APTR
)req
->ios2_BufferManagement
;
224 Remove((struct Node
*)opener
);
226 FreeVecPooled(FECBase
->feb_Pool
, opener
);
233 ADD2INITLIB(FEC_Init
,0)
234 ADD2OPENDEV(FEC_Open
,0)
235 ADD2CLOSEDEV(FEC_Close
,0)
237 AROS_LH1(void, beginio
,
238 AROS_LHA(struct IOSana2Req
*, req
, A1
),
239 LIBBASETYPEPTR
, LIBBASE
, 5, FEC
)
243 struct FECUnit
*unit
;
245 req
->ios2_Req
.io_Error
= 0;
246 unit
= (APTR
)req
->ios2_Req
.io_Unit
;
250 D(bug("[FEC] BeginIO\n"));
252 if (AttemptSemaphore(&unit
->feu_Lock
))
254 handle_request(LIBBASE
, req
);
258 req
->ios2_Req
.io_Flags
&= ~IOF_QUICK
;
259 PutMsg(unit
->feu_InputPort
, (struct Message
*)req
);
266 AROS_LH1(LONG
, abortio
,
267 AROS_LHA(struct IOSana2Req
*, req
, A1
),
268 LIBBASETYPEPTR
, LIBBASE
, 6, FEC
)
272 struct FECUnit
*unit
;
273 unit
= (APTR
)req
->ios2_Req
.io_Unit
;
277 D(bug("[FEC] AbortIO\n"));
280 if ((req
->ios2_Req
.io_Message
.mn_Node
.ln_Type
== NT_MESSAGE
) &&
281 (req
->ios2_Req
.io_Flags
& IOF_QUICK
) == 0)
283 Remove((struct Node
*)req
);
284 req
->ios2_Req
.io_Error
= IOERR_ABORTED
;
285 req
->ios2_WireError
= S2WERR_GENERIC_ERROR
;
286 ReplyMsg((struct Message
*)req
);