Fixed binary search: no more infinite loops when vendor is unknown.
[tangerine.git] / workbench / devs / networks / intelpro100 / os4_device.c
blob7d67efdd20849b6fa5bd90acea5cd3b98eecdd0f
1 /*
3 Copyright (C) 2000-2005 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>
30 #include <proto/exec.h>
31 #include <clib/alib_protos.h>
32 #include <proto/utility.h>
34 #include "device.h"
36 #include "unit_protos.h"
37 #include "pci_protos.h"
38 #include "request_protos.h"
41 /* Private prototypes */
43 static struct DevBase *DevInit(struct DevBase *dev_base, APTR seg_list,
44 struct ExecIFace *i_exec);
45 static ULONG IfaceObtain(struct Interface *self);
46 static ULONG IfaceRelease(struct Interface *self);
47 static LONG DevOpen(struct Interface *self, struct IOSana2Req *request,
48 ULONG unit_num, ULONG flags);
49 static APTR DevClose(struct Interface *self, struct IOSana2Req *request);
50 static APTR DevExpunge(struct Interface *self);
51 static VOID DevBeginIO(struct Interface *self, struct IOSana2Req *request);
52 static VOID DevAbortIO(struct Interface *self, struct IOSana2Req *request);
53 static VOID DeleteDevice(struct DevBase *base);
54 static struct DevUnit *GetUnit(ULONG unit_num, struct DevBase *base);
55 static BOOL RXFunction(struct IOSana2Req *request, APTR buffer, ULONG size);
56 static BOOL TXFunction(APTR buffer, struct IOSana2Req *request, ULONG size);
57 static UBYTE *DMATXFunction(struct IOSana2Req *request);
58 static ULONG OS4Int(struct ExceptionContext ex_context,
59 struct ExecBase *sys_base, APTR *int_data);
62 extern const APTR vectors[];
63 extern const struct TagItem init_tags[];
66 /* Return an error immediately if someone tries to run the device */
68 LONG Main()
70 return -1;
73 const TEXT device_name[] = DEVICE_NAME;
74 static const TEXT version_string[] =
75 DEVICE_NAME " " STR(VERSION) "." STR(REVISION) " (" DATE ")\n";
76 static const TEXT manager_name[] = "__device";
77 static const TEXT utility_name[] = UTILITYNAME;
78 static const TEXT expansion_name[] = EXPANSIONNAME;
79 static const TEXT timer_name[] = TIMERNAME;
82 const struct Resident rom_tag =
84 RTC_MATCHWORD,
85 (struct Resident *)&rom_tag,
86 (APTR)(&rom_tag + 1),
87 RTF_AUTOINIT | RTF_NATIVE,
88 VERSION,
89 NT_DEVICE,
91 (STRPTR)device_name,
92 (STRPTR)version_string,
93 (APTR)init_tags
97 static const APTR manager_vectors[] =
99 (APTR)IfaceObtain,
100 (APTR)IfaceRelease,
101 (APTR)NULL,
102 (APTR)NULL,
103 (APTR)DevOpen,
104 (APTR)DevClose,
105 (APTR)DevExpunge,
106 (APTR)NULL,
107 (APTR)DevBeginIO,
108 (APTR)DevAbortIO,
109 (APTR)-1
113 static const struct TagItem manager_tags[] =
115 {MIT_Name, (UPINT)manager_name},
116 {MIT_VectorTable, (UPINT)manager_vectors},
117 {MIT_Version, 1},
118 {TAG_END, 0}
122 static const struct TagItem *interfaces[] =
124 manager_tags,
125 NULL
129 static const struct TagItem init_tags[] =
131 {CLT_DataSize, sizeof(struct DevBase)},
132 {CLT_InitFunc, (UPINT)DevInit},
133 {CLT_Interfaces, (UPINT)interfaces},
134 {TAG_END, 0}
138 static const ULONG rx_tags[] =
140 S2_CopyToBuff,
141 S2_CopyToBuff16,
145 static const ULONG tx_tags[] =
147 S2_CopyFromBuff,
148 S2_CopyFromBuff16,
149 S2_CopyFromBuff32
154 /****i* intelpro100.device/DevInit *****************************************
156 * NAME
157 * DevInit
159 * SYNOPSIS
160 * dev_base = DevInit(dev_base, seg_list, i_exec)
162 * struct DevBase *DevInit(struct DevBase *, APTR, ExecIFace *);
164 ****************************************************************************
168 static struct DevBase *DevInit(struct DevBase *dev_base, APTR seg_list,
169 struct ExecIFace *i_exec)
171 struct DevBase *base;
172 BOOL success = TRUE;
174 dev_base->i_exec = i_exec;
175 base = dev_base;
176 base->seg_list = seg_list;
177 base->sys_base = (APTR)i_exec->Data.LibBase;
179 base->device.dd_Library.lib_Node.ln_Type = NT_DEVICE;
180 base->device.dd_Library.lib_Node.ln_Name = (TEXT *)device_name;
181 base->device.dd_Library.lib_Flags = LIBF_SUMUSED | LIBF_CHANGED;
182 base->device.dd_Library.lib_Version = VERSION;
183 base->device.dd_Library.lib_Revision = REVISION;
184 base->device.dd_Library.lib_IdString = (TEXT *)version_string;
187 base->utility_base = (APTR)OpenLibrary(utility_name, UTILITY_VERSION);
188 base->expansion_base = OpenLibrary(expansion_name, EXPANSION_VERSION);
189 if(base->utility_base == NULL || base->expansion_base == NULL)
190 success = FALSE;
192 if(OpenDevice(timer_name, UNIT_VBLANK, (APTR)&base->timer_request, 0) !=
194 success = FALSE;
196 NewList((APTR)(&dev_base->pci_units));
197 base->wrapper_int_code = (APTR)OS4Int;
199 if(success)
201 base->i_utility =
202 (APTR)GetInterface((APTR)UtilityBase, "main", 1, NULL);
203 base->i_pci =
204 (APTR)GetInterface(ExpansionBase, "pci", 1, NULL);
205 base->i_timer =
206 (APTR)GetInterface((APTR)TimerBase, "main", 1, NULL);
207 if(base->i_utility == NULL || base->i_pci == NULL
208 || base->i_timer == NULL)
209 success = FALSE;
212 if(!success)
214 DeleteDevice(base);
215 base = NULL;
218 return base;
223 /****i* intelpro100.device/IfaceObtain *************************************
225 * NAME
226 * IfaceObtain
228 * SYNOPSIS
229 * ref_count = IfaceObtain(self)
231 * ULONG IfaceObtain(struct Interface *);
233 ****************************************************************************
237 static ULONG IfaceObtain(struct Interface *self)
239 return self->Data.RefCount++;
244 /****i* intelpro100.device/IfaceRelease ************************************
246 * NAME
247 * IfaceRelease
249 * SYNOPSIS
250 * ref_count = IfaceRelease(self)
252 * ULONG IfaceRelease(struct Interface *);
254 ****************************************************************************
258 static ULONG IfaceRelease(struct Interface *self)
260 return --self->Data.RefCount;
265 /****i* intelpro100.device/DevOpen *****************************************
267 * NAME
268 * DevOpen
270 * SYNOPSIS
271 * error = DevOpen(self, request, unit_num, flags)
273 * LONG DevOpen(struct Interface *, struct IOSana2Req *, ULONG, ULONG);
275 ****************************************************************************
279 static LONG DevOpen(struct Interface *self, struct IOSana2Req *request,
280 ULONG unit_num, ULONG flags)
282 struct DevBase *base;
283 struct DevUnit *unit;
284 BYTE error = 0;
285 struct Opener *opener;
286 struct TagItem *tag_list;
287 UWORD i;
289 base = (APTR)self->Data.LibBase;
290 base->device.dd_Library.lib_OpenCnt++;
291 base->device.dd_Library.lib_Flags &= ~LIBF_DELEXP;
293 request->ios2_Req.io_Unit = NULL;
294 tag_list = request->ios2_BufferManagement;
295 request->ios2_BufferManagement = NULL;
297 /* Check request size */
299 if(request->ios2_Req.io_Message.mn_Length < sizeof(struct IOSana2Req))
300 error = IOERR_OPENFAIL;
302 /* Get the requested unit */
304 if(error == 0)
306 request->ios2_Req.io_Unit = (APTR)(unit = GetUnit(unit_num, base));
307 if(unit == NULL)
308 error = IOERR_OPENFAIL;
311 /* Handle device sharing */
313 if(error == 0)
315 if((unit->open_count != 0) && (((unit->flags & UNITF_SHARED) == 0)
316 || ((flags & SANA2OPF_MINE) != 0)))
317 error = IOERR_UNITBUSY;
318 unit->open_count++;
321 if(error == 0)
323 if((flags & SANA2OPF_MINE) == 0)
324 unit->flags |= UNITF_SHARED;
325 else if((flags & SANA2OPF_PROM) != 0)
326 unit->flags |= UNITF_PROM;
328 /* Set up buffer-management structure and get hooks */
330 request->ios2_BufferManagement = opener =
331 AllocVec(sizeof(struct Opener), MEMF_PUBLIC | MEMF_CLEAR);
332 if(opener == NULL)
333 error = IOERR_OPENFAIL;
336 if(error == 0)
338 NewList(&opener->read_port.mp_MsgList);
339 opener->read_port.mp_Flags = PA_IGNORE;
340 NewList((APTR)&opener->initial_stats);
342 for(i = 0; i < 2; i++)
343 opener->real_rx_function = (APTR)GetTagData(rx_tags[i],
344 (UPINT)opener->real_rx_function, tag_list);
345 for(i = 0; i < 3; i++)
346 opener->real_tx_function = (APTR)GetTagData(tx_tags[i],
347 (UPINT)opener->real_tx_function, tag_list);
349 opener->filter_hook = (APTR)GetTagData(S2_PacketFilter, (UPINT)NULL,
350 tag_list);
351 opener->real_dma_tx_function =
352 (APTR)GetTagData(S2_DMACopyFromBuff32, (UPINT)NULL, tag_list);
354 opener->rx_function = (APTR)RXFunction;
355 opener->tx_function = (APTR)TXFunction;
356 if(opener->real_dma_tx_function != NULL)
357 opener->dma_tx_function = (APTR)DMATXFunction;
359 Disable();
360 AddTail((APTR)&unit->openers, (APTR)opener);
361 Enable();
364 /* Back out if anything went wrong */
366 if(error != 0)
367 DevClose(self, request);
369 /* Return */
371 request->ios2_Req.io_Error = error;
372 return error;
377 /****i* intelpro100.device/DevClose ****************************************
379 * NAME
380 * DevClose
382 * SYNOPSIS
383 * seg_list = DevClose(request)
385 * APTR DevClose(struct IOSana2Req *);
387 ****************************************************************************
391 static APTR DevClose(struct Interface *self, struct IOSana2Req *request)
393 struct DevBase *base;
394 struct DevUnit *unit;
395 APTR seg_list;
396 struct Opener *opener;
398 /* Free buffer-management resources */
400 base = (APTR)self->Data.LibBase;
401 opener = (APTR)request->ios2_BufferManagement;
402 if(opener != NULL)
404 Disable();
405 Remove((APTR)opener);
406 Enable();
407 FreeVec(opener);
410 /* Delete the unit if it's no longer in use */
412 unit = (APTR)request->ios2_Req.io_Unit;
413 if(unit != NULL)
415 if((--unit->open_count) == 0)
417 Remove((APTR)unit);
418 switch(unit->bus)
420 case PCI_BUS:
421 DeletePCIUnit(unit, base);
426 /* Expunge the device if a delayed expunge is pending */
428 seg_list = NULL;
430 if((--base->device.dd_Library.lib_OpenCnt) == 0)
432 if((base->device.dd_Library.lib_Flags & LIBF_DELEXP) != 0)
433 seg_list = DevExpunge(self);
436 return seg_list;
441 /****i* intelpro100.device/DevExpunge **************************************
443 * NAME
444 * DevExpunge
446 * SYNOPSIS
447 * seg_list = DevExpunge()
449 * APTR DevExpunge(VOID);
451 ****************************************************************************
455 static APTR DevExpunge(struct Interface *self)
457 struct DevBase *base;
458 APTR seg_list;
460 base = (APTR)self->Data.LibBase;
461 if(base->device.dd_Library.lib_OpenCnt == 0)
463 seg_list = base->seg_list;
464 Remove((APTR)base);
465 DeleteDevice(base);
467 else
469 base->device.dd_Library.lib_Flags |= LIBF_DELEXP;
470 seg_list = NULL;
473 return seg_list;
478 /****i* intelpro100.device/DevBeginIO **************************************
480 * NAME
481 * DevBeginIO
483 * SYNOPSIS
484 * DevBeginIO(request)
486 * VOID DevBeginIO(struct IORequest *);
488 ****************************************************************************
492 static VOID DevBeginIO(struct Interface *self, struct IOSana2Req *request)
494 struct DevBase *base;
495 struct DevUnit *unit;
497 /* Replace caller's cookie with our own */
499 base = (APTR)self->Data.LibBase;
500 request->ios2_Req.io_Error = 0;
501 unit = (APTR)request->ios2_Req.io_Unit;
502 switch(request->ios2_Req.io_Command)
504 case CMD_READ:
505 case CMD_WRITE:
506 case S2_MULTICAST:
507 case S2_BROADCAST:
508 case S2_READORPHAN:
509 request->ios2_StatData = request->ios2_Data;
510 request->ios2_Data = request;
513 /* Send request for processing */
515 if(AttemptSemaphore(&unit->access_lock))
516 ServiceRequest(request, base);
517 else
519 PutRequest(unit->request_ports[GENERAL_QUEUE], (APTR)request, base);
522 return;
527 /****i* intelpro100.device/DevAbortIO **************************************
529 * NAME
530 * DevAbortIO -- Try to stop a request.
532 * SYNOPSIS
533 * DevAbortIO(request)
535 * VOID DevAbortIO(struct IOSana2Req *);
537 ****************************************************************************
539 * Disable() used instead of a semaphore because device uses interrupts.
543 static VOID DevAbortIO(struct Interface *self, struct IOSana2Req *request)
545 struct DevBase *base;
546 struct DevUnit *unit;
548 base = (APTR)self->Data.LibBase;
549 unit = (APTR)request->ios2_Req.io_Unit;
551 Disable();
552 if((request->ios2_Req.io_Message.mn_Node.ln_Type == NT_MESSAGE)
553 && ((request->ios2_Req.io_Flags & IOF_QUICK) == 0))
555 Remove((APTR)request);
556 request->ios2_Req.io_Error = IOERR_ABORTED;
557 request->ios2_WireError = S2WERR_GENERIC_ERROR;
558 ReplyMsg((APTR)request);
560 Enable();
562 return;
567 /****i* intelpro100.device/DeleteDevice ************************************
569 * NAME
570 * DeleteDevice
572 * SYNOPSIS
573 * DeleteDevice()
575 * VOID DeleteDevice(VOID);
577 ****************************************************************************
581 static VOID DeleteDevice(struct DevBase *base)
583 /* Close interfaces */
585 DropInterface((APTR)base->i_timer);
586 DropInterface((APTR)base->i_pci);
587 DropInterface((APTR)base->i_utility);
589 /* Close devices */
591 CloseDevice((APTR)&base->timer_request);
593 /* Close libraries */
595 if(base->expansion_base != NULL)
596 CloseLibrary(base->expansion_base);
597 if(base->utility_base != NULL)
598 CloseLibrary((APTR)base->utility_base);
600 /* Free device's memory */
602 DeleteLibrary((APTR)base);
604 return;
609 /****i* intelpro100.device/GetUnit *****************************************
611 * NAME
612 * GetUnit -- Get a unit by number.
614 * SYNOPSIS
615 * unit = GetUnit(unit_num)
617 * struct DevUnit *GetUnit(ULONG);
619 ****************************************************************************
623 static struct DevUnit *GetUnit(ULONG unit_num, struct DevBase *base)
625 struct DevUnit *unit;
626 ULONG pci_limit;
628 pci_limit = GetPCICount(base);
630 if(unit_num < pci_limit)
631 unit = GetPCIUnit(unit_num, base);
632 else
633 unit = NULL;
635 return unit;
640 /****i* intelpro100.device/RXFunction **************************************
642 * NAME
643 * RXFunction
645 ****************************************************************************
649 static BOOL RXFunction(struct IOSana2Req *request, APTR buffer, ULONG size)
651 struct DevBase *base;
652 struct Opener *opener;
653 APTR cookie;
655 opener = request->ios2_BufferManagement;
656 cookie = request->ios2_StatData;
657 base = (struct DevBase *)request->ios2_Req.io_Device;
658 request->ios2_Data = cookie;
660 return EmulateTags(opener->real_rx_function,
661 ET_RegisterA0, cookie, ET_RegisterA1, buffer,
662 ET_RegisterD0, size, TAG_END);
667 /****i* intelpro100.device/TXFunction **************************************
669 * NAME
670 * TXFunction
672 ****************************************************************************
676 static BOOL TXFunction(APTR buffer, struct IOSana2Req *request, ULONG size)
678 struct DevBase *base;
679 struct Opener *opener;
680 APTR cookie;
682 opener = request->ios2_BufferManagement;
683 cookie = request->ios2_StatData;
684 base = (struct DevBase *)request->ios2_Req.io_Device;
685 request->ios2_Data = cookie;
686 return EmulateTags(opener->real_tx_function,
687 ET_RegisterA0, buffer, ET_RegisterA1, cookie,
688 ET_RegisterD0, size, TAG_END);
693 /****i* intelpro100.device/DMATXFunction ***********************************
695 * NAME
696 * DMATXFunction
698 ****************************************************************************
702 static UBYTE *DMATXFunction(struct IOSana2Req *request)
704 struct DevBase *base;
705 struct Opener *opener;
706 APTR cookie;
708 opener = request->ios2_BufferManagement;
709 cookie = request->ios2_StatData;
710 base = (struct DevBase *)request->ios2_Req.io_Device;
711 request->ios2_Data = cookie;
712 return (UBYTE *)EmulateTags(opener->real_dma_tx_function,
713 ET_RegisterA0, cookie, TAG_END);
718 /****i* intelpro100.device/OS4Int ******************************************
720 * NAME
721 * OS4Int
723 ****************************************************************************
727 static ULONG OS4Int(struct ExceptionContext ex_context,
728 struct ExecBase *sys_base, APTR *int_data)
730 BOOL (*int_code)(APTR, APTR);
732 int_code = int_data[0];
733 return int_code(int_data[1], int_code);