Fixed binary search: no more infinite loops when vendor is unknown.
[tangerine.git] / workbench / devs / networks / etherlink3 / os4_device.c
blobb6199afddcfdf4d4cfb509916d692b97e8c4bdba
1 /*
3 Copyright (C) 2000-2006 Neil Cafferkey
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 MA 02111-1307, USA.
23 #include <exec/types.h>
24 #include <exec/resident.h>
25 #include <exec/errors.h>
26 #include <exec/emulation.h>
27 #include <utility/utility.h>
28 #include <expansion/expansion.h>
29 #include <resources/card.h>
30 #include <libraries/pccard.h>
32 #include <proto/exec.h>
33 #include <clib/alib_protos.h>
34 #include <proto/utility.h>
36 #include "device.h"
38 #include "device_protos.h"
39 #include "unit_protos.h"
40 #include "pci_protos.h"
41 #include "request_protos.h"
44 /* Private prototypes */
46 static struct DevBase *OS4DevInit(struct DevBase *dev_base, APTR seg_list,
47 struct ExecIFace *i_exec);
48 static ULONG IfaceObtain(struct Interface *self);
49 static ULONG IfaceRelease(struct Interface *self);
50 static LONG OS4DevOpen(struct Interface *self, struct IOSana2Req *request,
51 ULONG unit_num, ULONG flags);
52 static APTR OS4DevClose(struct Interface *self, struct IOSana2Req *request);
53 static APTR OS4DevExpunge(struct Interface *self);
54 static VOID OS4DevBeginIO(struct Interface *self,
55 struct IOSana2Req *request);
56 static VOID OS4DevAbortIO(struct Interface *self,
57 struct IOSana2Req *request);
58 static VOID DeleteDevice(struct DevBase *base);
59 static BOOL RXFunction(struct IOSana2Req *request, APTR buffer, ULONG size);
60 static BOOL TXFunction(APTR buffer, struct IOSana2Req *request, ULONG size);
61 static UBYTE *DMATXFunction(struct IOSana2Req *request);
62 static ULONG OS4Int(struct ExceptionContext ex_context,
63 struct ExecBase *sys_base, APTR *int_data);
66 extern const TEXT device_name[];
67 extern const TEXT version_string[];
68 extern const TEXT utility_name[];
69 extern const TEXT pccard_name[];
70 extern const TEXT card_name[];
71 extern const TEXT timer_name[];
72 extern const struct Resident rom_tag;
74 static const TEXT manager_name[] = "__device";
75 static const TEXT expansion_name[] = EXPANSIONNAME;
78 static const APTR manager_vectors[] =
80 (APTR)IfaceObtain,
81 (APTR)IfaceRelease,
82 (APTR)NULL,
83 (APTR)NULL,
84 (APTR)OS4DevOpen,
85 (APTR)OS4DevClose,
86 (APTR)OS4DevExpunge,
87 (APTR)NULL,
88 (APTR)OS4DevBeginIO,
89 (APTR)OS4DevAbortIO,
90 (APTR)-1
94 static const struct TagItem manager_tags[] =
96 {MIT_Name, (UPINT)manager_name},
97 {MIT_VectorTable, (UPINT)manager_vectors},
98 {MIT_Version, 1},
99 {TAG_END, 0}
103 static const struct TagItem *interfaces[] =
105 manager_tags,
106 NULL
110 static const struct TagItem init_tags[] =
112 {CLT_DataSize, sizeof(struct DevBase)},
113 {CLT_InitFunc, (UPINT)OS4DevInit},
114 {CLT_Interfaces, (UPINT)interfaces},
115 {TAG_END, 0}
119 const struct Resident os4_rom_tag =
121 RTC_MATCHWORD,
122 (struct Resident *)&os4_rom_tag,
123 (APTR)(&rom_tag + 1),
124 RTF_AUTOINIT | RTF_NATIVE,
125 VERSION,
126 NT_DEVICE,
128 (STRPTR)device_name,
129 (STRPTR)version_string,
130 (APTR)init_tags
134 static const ULONG rx_tags[] =
136 S2_CopyToBuff,
137 S2_CopyToBuff16,
141 static const ULONG tx_tags[] =
143 S2_CopyFromBuff,
144 S2_CopyFromBuff16,
145 S2_CopyFromBuff32
150 /****i* etherlink3.device/OS4DevInit ***************************************
152 * NAME
153 * OS4DevInit
155 * SYNOPSIS
156 * dev_base = OS4DevInit(dev_base, seg_list, i_exec)
158 * struct DevBase *OS4DevInit(struct DevBase *, APTR, ExecIFace *);
160 ****************************************************************************
164 static struct DevBase *OS4DevInit(struct DevBase *dev_base, APTR seg_list,
165 struct ExecIFace *i_exec)
167 struct DevBase *base;
168 BOOL success = TRUE;
170 dev_base->i_exec = i_exec;
171 base = dev_base;
172 base->seg_list = seg_list;
173 base->sys_base = (APTR)i_exec->Data.LibBase;
175 base->device.dd_Library.lib_Node.ln_Type = NT_DEVICE;
176 base->device.dd_Library.lib_Node.ln_Name = (TEXT *)device_name;
177 base->device.dd_Library.lib_Flags = LIBF_SUMUSED | LIBF_CHANGED;
178 base->device.dd_Library.lib_Version = VERSION;
179 base->device.dd_Library.lib_Revision = REVISION;
180 base->device.dd_Library.lib_IdString = (TEXT *)version_string;
183 base->utility_base = (APTR)OpenLibrary(utility_name, UTILITY_VERSION);
184 base->expansion_base = OpenLibrary(expansion_name, EXPANSION_VERSION);
185 if(base->utility_base == NULL || base->expansion_base == NULL)
186 success = FALSE;
187 base->card_base = (APTR)OpenResource(card_name);
188 base->pccard_base = (APTR)OpenLibrary(pccard_name, PCCARD_VERSION);
190 if(OpenDevice(timer_name, UNIT_ECLOCK, (APTR)&base->timer_request, 0) !=
192 success = FALSE;
194 NewList((APTR)(&dev_base->pci_units));
195 NewList((APTR)(&dev_base->pccard_units));
196 base->wrapper_int_code = (APTR)OS4Int;
198 if(success)
200 base->i_utility =
201 (APTR)GetInterface((APTR)UtilityBase, "main", 1, NULL);
202 base->i_pci =
203 (APTR)GetInterface(ExpansionBase, "pci", 1, NULL);
204 base->i_timer =
205 (APTR)GetInterface((APTR)TimerBase, "main", 1, NULL);
206 if(base->i_utility == NULL || base->i_pci == NULL
207 || base->i_timer == NULL)
208 success = FALSE;
211 if(!success)
213 DeleteDevice(base);
214 base = NULL;
217 return base;
222 /****i* etherlink3.device/IfaceObtain **************************************
224 * NAME
225 * IfaceObtain
227 * SYNOPSIS
228 * ref_count = IfaceObtain(self)
230 * ULONG IfaceObtain(struct Interface *);
232 ****************************************************************************
236 static ULONG IfaceObtain(struct Interface *self)
238 return self->Data.RefCount++;
243 /****i* etherlink3.device/IfaceRelease *************************************
245 * NAME
246 * IfaceRelease
248 * SYNOPSIS
249 * ref_count = IfaceRelease(self)
251 * ULONG IfaceRelease(struct Interface *);
253 ****************************************************************************
257 static ULONG IfaceRelease(struct Interface *self)
259 return --self->Data.RefCount;
264 /****i* etherlink3.device/OS4DevOpen ***************************************
266 * NAME
267 * OS4DevOpen
269 * SYNOPSIS
270 * error = OS4DevOpen(self, request, unit_num,
271 * flags)
273 * LONG OS4DevOpen(struct Interface *, struct IOSana2Req *, ULONG,
274 * ULONG);
276 ****************************************************************************
280 static LONG OS4DevOpen(struct Interface *self, struct IOSana2Req *request,
281 ULONG unit_num, ULONG flags)
283 struct Opener *opener;
284 BYTE error;
286 error = DevOpen(request, unit_num, flags, (APTR)self->Data.LibBase);
288 /* Set up wrapper hooks to hide 68k emulation */
290 if(error == 0)
292 opener = request->ios2_BufferManagement;
293 opener->real_rx_function = opener->rx_function;
294 opener->real_tx_function = opener->tx_function;
295 opener->rx_function = (APTR)RXFunction;
296 opener->tx_function = (APTR)TXFunction;
297 if(opener->dma_tx_function != NULL)
299 opener->real_dma_tx_function = opener->dma_tx_function;
300 opener->dma_tx_function = (APTR)DMATXFunction;
304 return error;
309 /****i* etherlink3.device/OS4DevClose **************************************
311 * NAME
312 * OS4DevClose
314 * SYNOPSIS
315 * seg_list = OS4DevClose(request)
317 * APTR OS4DevClose(struct IOSana2Req *);
319 ****************************************************************************
323 static APTR OS4DevClose(struct Interface *self, struct IOSana2Req *request)
325 struct DevBase *base;
326 APTR seg_list = NULL;
328 /* Close the unit */
330 base = (APTR)self->Data.LibBase;
331 CloseUnit(request, base);
333 /* Expunge the device if a delayed expunge is pending */
335 if(base->device.dd_Library.lib_OpenCnt == 0)
337 if((base->device.dd_Library.lib_Flags & LIBF_DELEXP) != 0)
338 seg_list = OS4DevExpunge(self);
341 return seg_list;
346 /****i* etherlink3.device/OS4DevExpunge ************************************
348 * NAME
349 * OS4DevExpunge
351 * SYNOPSIS
352 * seg_list = OS4DevExpunge()
354 * APTR OS4DevExpunge(VOID);
356 ****************************************************************************
360 static APTR OS4DevExpunge(struct Interface *self)
362 struct DevBase *base;
363 APTR seg_list;
365 base = (APTR)self->Data.LibBase;
366 if(base->device.dd_Library.lib_OpenCnt == 0)
368 seg_list = base->seg_list;
369 Remove((APTR)base);
370 DeleteDevice(base);
372 else
374 base->device.dd_Library.lib_Flags |= LIBF_DELEXP;
375 seg_list = NULL;
378 return seg_list;
383 /****i* etherlink3.device/OS4DevBeginIO ************************************
385 * NAME
386 * OS4DevBeginIO
388 * SYNOPSIS
389 * OS4DevBeginIO(request)
391 * VOID OS4DevBeginIO(struct IORequest *);
393 ****************************************************************************
397 static VOID OS4DevBeginIO(struct Interface *self,
398 struct IOSana2Req *request)
400 /* Replace caller's cookie with our own */
402 request->ios2_Req.io_Error = 0;
403 switch(request->ios2_Req.io_Command)
405 case CMD_READ:
406 case CMD_WRITE:
407 case S2_MULTICAST:
408 case S2_BROADCAST:
409 case S2_READORPHAN:
410 request->ios2_StatData = request->ios2_Data;
411 request->ios2_Data = request;
414 /* Send request for processing */
416 DevBeginIO(request, (APTR)self->Data.LibBase);
418 return;
423 /****i* etherlink3.device/OS4DevAbortIO ************************************
425 * NAME
426 * OS4DevAbortIO -- Try to stop a request.
428 * SYNOPSIS
429 * OS4DevAbortIO(request)
431 * VOID OS4DevAbortIO(struct IOSana2Req *);
433 ****************************************************************************
435 * Disable() used instead of a semaphore because device uses interrupts.
439 static VOID OS4DevAbortIO(struct Interface *self,
440 struct IOSana2Req *request)
442 DevAbortIO(request, (APTR)self->Data.LibBase);
444 return;
449 /****i* etherlink3.device/DeleteDevice *************************************
451 * NAME
452 * DeleteDevice
454 * SYNOPSIS
455 * DeleteDevice()
457 * VOID DeleteDevice(VOID);
459 ****************************************************************************
463 static VOID DeleteDevice(struct DevBase *base)
465 /* Close interfaces */
467 DropInterface((APTR)base->i_timer);
468 DropInterface((APTR)base->i_pci);
469 DropInterface((APTR)base->i_utility);
471 /* Close devices */
473 CloseDevice((APTR)&base->timer_request);
475 /* Close libraries */
477 if(base->expansion_base != NULL)
478 CloseLibrary(base->expansion_base);
479 if(base->utility_base != NULL)
480 CloseLibrary((APTR)base->utility_base);
482 /* Free device's memory */
484 DeleteLibrary((APTR)base);
486 return;
491 /****i* etherlink3.device/RXFunction ***************************************
493 * NAME
494 * RXFunction
496 ****************************************************************************
500 static BOOL RXFunction(struct IOSana2Req *request, APTR buffer, ULONG size)
502 struct DevBase *base;
503 struct Opener *opener;
504 APTR cookie;
506 opener = request->ios2_BufferManagement;
507 cookie = request->ios2_StatData;
508 base = (struct DevBase *)request->ios2_Req.io_Device;
509 request->ios2_Data = cookie;
511 return EmulateTags(opener->real_rx_function,
512 ET_RegisterA0, cookie, ET_RegisterA1, buffer,
513 ET_RegisterD0, size, TAG_END);
518 /****i* etherlink3.device/TXFunction ***************************************
520 * NAME
521 * TXFunction
523 ****************************************************************************
527 static BOOL TXFunction(APTR buffer, struct IOSana2Req *request, ULONG size)
529 struct DevBase *base;
530 struct Opener *opener;
531 APTR cookie;
533 opener = request->ios2_BufferManagement;
534 cookie = request->ios2_StatData;
535 base = (struct DevBase *)request->ios2_Req.io_Device;
536 request->ios2_Data = cookie;
537 return EmulateTags(opener->real_tx_function,
538 ET_RegisterA0, buffer, ET_RegisterA1, cookie,
539 ET_RegisterD0, size, TAG_END);
544 /****i* etherlink3.device/DMATXFunction ************************************
546 * NAME
547 * DMATXFunction
549 ****************************************************************************
553 static UBYTE *DMATXFunction(struct IOSana2Req *request)
555 struct DevBase *base;
556 struct Opener *opener;
557 APTR cookie;
559 opener = request->ios2_BufferManagement;
560 cookie = request->ios2_StatData;
561 base = (struct DevBase *)request->ios2_Req.io_Device;
562 request->ios2_Data = cookie;
563 return (UBYTE *)EmulateTags(opener->real_dma_tx_function,
564 ET_RegisterA0, cookie, TAG_END);
569 /****i* etherlink3.device/OS4Int *******************************************
571 * NAME
572 * OS4Int
574 ****************************************************************************
578 static ULONG OS4Int(struct ExceptionContext ex_context,
579 struct ExecBase *sys_base, APTR *int_data)
581 BOOL (*int_code)(APTR, APTR);
583 int_code = int_data[0];
584 return int_code(int_data[1], int_code);