Fixed binary search: no more infinite loops when vendor is unknown.
[tangerine.git] / workbench / devs / networks / intelpro100 / pci.c
blobd02986c9800c9f0ef8f449de1f4dcae87f3728e8
1 /*
3 Copyright (C) 2004,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 <utility/tagitem.h>
26 #ifdef __amigaos4__
27 #include <expansion/pci.h>
28 #endif
30 #include <proto/exec.h>
31 #include <proto/expansion.h>
33 #include "device.h"
34 #include "pci.h"
36 #include "pci_protos.h"
37 #include "prometheus_protos.h"
38 #include "powerpci_protos.h"
39 #include "expansion_protos.h"
40 #include "openpci_protos.h"
41 #include "unit_protos.h"
44 /* Private prototypes */
46 static struct DevUnit *FindPCIUnit(ULONG index, struct DevBase *base);
47 static struct DevUnit *CreatePCIUnit(ULONG index, struct DevBase *base);
48 static struct BusContext *AllocCard(ULONG index, struct DevBase *base);
49 static VOID FreeCard(struct BusContext *context, struct DevBase *base);
50 static BOOL AddPCIIntServer(APTR card, struct Interrupt *interrupt,
51 struct DevBase *base);
52 static VOID RemPCIIntServer(APTR card, struct Interrupt *interrupt,
53 struct DevBase *base);
54 static UBYTE ByteInHook(struct BusContext *context, ULONG offset);
55 static VOID ByteOutHook(struct BusContext *context, ULONG offset,
56 UBYTE value);
57 static UWORD LEWordInHook(struct BusContext *context, ULONG offset);
58 static ULONG LELongInHook(struct BusContext *context, ULONG offset);
59 static VOID LEWordOutHook(struct BusContext *context, ULONG offset,
60 UWORD value);
61 static VOID LELongOutHook(struct BusContext *context, ULONG offset,
62 ULONG value);
63 static APTR AllocDMAMemHook(struct BusContext *context, UPINT size,
64 UWORD alignment);
65 static VOID FreeDMAMemHook(struct BusContext *context, APTR mem);
66 static BOOL WrapInt(struct Interrupt *interrupt, struct DevBase *base);
67 static VOID UnwrapInt(struct Interrupt *interrupt, struct DevBase *base);
70 const UWORD product_codes[] =
72 0x8086, 0x1029,
73 0x8086, 0x1030,
74 0x8086, 0x1031,
75 0x8086, 0x1032,
76 0x8086, 0x1033,
77 0x8086, 0x1034,
78 0x8086, 0x1035,
79 0x8086, 0x1036,
80 0x8086, 0x1037,
81 0x8086, 0x1038,
82 0x8086, 0x1039,
83 0x8086, 0x103A,
84 0x8086, 0x103B,
85 0x8086, 0x103C,
86 0x8086, 0x103D,
87 0x8086, 0x103E,
88 0x8086, 0x1050,
89 0x8086, 0x1059,
90 0x8086, 0x1209,
91 0x8086, 0x1227,
92 0x8086, 0x1228,
93 0x8086, 0x1229,
94 0x8086, 0x2449,
95 0x8086, 0x2459,
96 0x8086, 0x245D,
97 0x8086, 0x5200,
98 0x8086, 0x5201,
99 0xffff, 0xffff
103 static const struct TagItem unit_tags[] =
105 {IOTAG_ByteIn, (UPINT)ByteInHook},
106 {IOTAG_ByteOut, (UPINT)ByteOutHook},
107 {IOTAG_LEWordIn, (UPINT)LEWordInHook},
108 {IOTAG_LELongIn, (UPINT)LELongInHook},
109 {IOTAG_LEWordOut, (UPINT)LEWordOutHook},
110 {IOTAG_LELongOut, (UPINT)LELongOutHook},
111 {IOTAG_AllocDMAMem, (UPINT)AllocDMAMemHook},
112 {IOTAG_FreeDMAMem, (UPINT)FreeDMAMemHook},
113 {TAG_END, 0}
117 /****i* intelpro100.device/GetPCICount *************************************
119 * NAME
120 * GetPCICount -- Get the number of compatible PCI Cards.
122 * SYNOPSIS
123 * count = GetPCICount()
125 * ULONG GetPCICount();
127 ****************************************************************************
131 ULONG GetPCICount(struct DevBase *base)
133 ULONG count = 0;
135 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
136 if(base->prometheus_base != NULL)
137 count = GetPrometheusCount(base);
138 #endif
139 #ifdef __mc68000__
140 if(base->powerpci_base != NULL)
141 count = GetPowerPCICount(base);
142 #endif
143 #ifdef __amigaos4__
144 if(base->expansion_base != NULL)
145 count = GetExpansionCount(base);
146 #endif
147 #ifdef __MORPHOS__
148 if(base->openpci_base != NULL)
149 count = GetOpenPCICount(base);
150 #endif
152 return count;
157 /****i* intelpro100.device/GetPCIUnit **************************************
159 * NAME
160 * GetPCIUnit -- Get a unit by number.
162 * SYNOPSIS
163 * unit = GetPCIUnit(index)
165 * struct DevUnit *GetPCIUnit(ULONG);
167 ****************************************************************************
171 struct DevUnit *GetPCIUnit(ULONG index, struct DevBase *base)
173 struct DevUnit *unit;
175 unit = FindPCIUnit(index, base);
177 if(unit == NULL)
179 unit = CreatePCIUnit(index, base);
180 if(unit != NULL)
182 AddTail((APTR)&base->pci_units, (APTR)unit);
186 return unit;
191 /****i* intelpro100.device/FindPCIUnit *************************************
193 * NAME
194 * FindPCIUnit -- Find a unit by number.
196 * SYNOPSIS
197 * unit = FindPCIUnit(index)
199 * struct DevUnit *FindPCIUnit(ULONG);
201 ****************************************************************************
205 static struct DevUnit *FindPCIUnit(ULONG index, struct DevBase *base)
207 struct DevUnit *unit, *tail;
208 BOOL found = FALSE;
210 unit = (APTR)base->pci_units.mlh_Head;
211 tail = (APTR)&base->pci_units.mlh_Tail;
213 while(unit != tail && !found)
215 if(unit->index == index)
216 found = TRUE;
217 else
218 unit = (APTR)unit->node.mln_Succ;
221 if(!found)
222 unit = NULL;
224 return unit;
229 /****i* intelpro100.device/CreatePCIUnit ***********************************
231 * NAME
232 * CreatePCIUnit -- Create a unit.
234 * SYNOPSIS
235 * unit = CreatePCIUnit(index)
237 * struct DevUnit *CreatePCIUnit(ULONG);
239 * FUNCTION
240 * Creates a PCI new unit.
242 ****************************************************************************
246 static struct DevUnit *CreatePCIUnit(ULONG index, struct DevBase *base)
248 BOOL success = TRUE;
249 struct BusContext *context;
250 struct DevUnit *unit = NULL;
252 context = AllocCard(index, base);
253 if(context == NULL)
254 success = FALSE;
256 if(success)
258 if(context->unit_tags == NULL)
260 context->unit_tags = unit_tags;
264 if(success)
266 context->device = base;
267 context->unit = unit =
268 CreateUnit(index, context, context->unit_tags, PCI_BUS, base);
269 if(unit == NULL)
270 success = FALSE;
273 /* Add interrupt */
275 if(success)
277 if(!(WrapInt(&unit->status_int, base)
278 && WrapInt(&unit->rx_int, base)
279 && WrapInt(&unit->tx_int, base)
280 && WrapInt(&unit->tx_end_int, base)))
281 success = FALSE;
282 success = AddPCIIntServer(context->card, &unit->status_int, base);
285 if(!success)
287 if(context != NULL)
289 DeleteUnit(context->unit, base);
290 FreeCard(context, base);
292 unit = NULL;
295 return unit;
300 /****i* intelpro100.device/DeletePCIUnit ***********************************
302 * NAME
303 * DeletePCIUnit -- Delete a unit.
305 * SYNOPSIS
306 * DeletePCIUnit(unit)
308 * VOID DeletePCIUnit(struct DevUnit *);
310 * FUNCTION
311 * Deletes a unit.
313 * INPUTS
314 * unit - Device unit (can be NULL).
316 * RESULT
317 * None.
319 ****************************************************************************
323 VOID DeletePCIUnit(struct DevUnit *unit, struct DevBase *base)
325 struct BusContext *context;
327 if(unit != NULL)
329 context = unit->card;
330 RemPCIIntServer(context->card, &unit->status_int, base);
331 UnwrapInt(&unit->tx_end_int, base);
332 UnwrapInt(&unit->tx_int, base);
333 UnwrapInt(&unit->rx_int, base);
334 UnwrapInt(&unit->status_int, base);
335 DeleteUnit(unit, base);
336 FreeCard(context, base);
339 return;
344 /****i* intelpro100.device/AllocCard ***************************************
346 * NAME
347 * AllocCard -- Get card from system.
349 * SYNOPSIS
350 * context = AllocCard(index)
352 * struct BusContext *AllocCard(ULONG);
354 ****************************************************************************
358 static struct BusContext *AllocCard(ULONG index, struct DevBase *base)
360 struct BusContext *context;
362 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
363 if(base->prometheus_base != NULL)
364 context = AllocPrometheusCard(index, base);
365 #endif
366 #ifdef __mc68000__
367 if(base->powerpci_base != NULL)
368 context = AllocPowerPCICard(index, base);
369 #endif
370 #ifdef __amigaos4__
371 if(base->expansion_base != NULL)
372 context = AllocExpansionCard(index, base);
373 #endif
374 #ifdef __MORPHOS__
375 if(base->openpci_base != NULL)
376 context = AllocOpenPCICard(index, base);
377 #endif
379 return context;
384 /****i* intelpro100.device/FreeCard ****************************************
386 * NAME
387 * FreeCard
389 * SYNOPSIS
390 * FreeCard(context)
392 * VOID FreeCard(struct BusContext *);
394 ****************************************************************************
398 static VOID FreeCard(struct BusContext *context, struct DevBase *base)
401 if(context != NULL)
403 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
404 if(base->prometheus_base != NULL)
405 FreePrometheusCard(context, base);
406 #endif
407 #ifdef __mc68000
408 if(base->powerpci_base != NULL)
409 FreePowerPCICard(context, base);
410 #endif
411 #ifdef __amigaos4__
412 if(base->expansion_base != NULL)
413 FreeExpansionCard(context, base);
414 #endif
415 #ifdef __MORPHOS__
416 if(base->openpci_base != NULL)
417 FreeOpenPCICard(context, base);
418 #endif
421 return;
426 /****i* intelpro100.device/AddPCIIntServer *********************************
428 * NAME
429 * AddPCIIntServer
431 * SYNOPSIS
432 * context = AddPCIIntServer(index)
434 * struct BusContext *AddPCIIntServer(ULONG);
436 ****************************************************************************
440 static BOOL AddPCIIntServer(APTR card, struct Interrupt *interrupt,
441 struct DevBase *base)
443 BOOL success;
445 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
446 if(base->prometheus_base != NULL)
447 success = AddPrometheusIntServer(card, interrupt, base);
448 #endif
449 #ifdef __mc68000
450 if(base->powerpci_base != NULL)
451 success = AddPowerPCIIntServer(card, interrupt, base);
452 #endif
453 #ifdef __amigaos4__
454 if(base->expansion_base != NULL)
455 success = AddExpansionIntServer(card, interrupt, base);
456 #endif
457 #ifdef __MORPHOS__
458 if(base->openpci_base != NULL)
459 success = AddOpenPCIIntServer(card, interrupt, base);
460 #endif
462 return success;
467 /****i* intelpro100.device/RemPCIIntServer *********************************
469 * NAME
470 * RemPCIIntServer
472 * SYNOPSIS
473 * RemPCIIntServer()
475 * VOID RemPCIIntServer(ULONG);
477 ****************************************************************************
481 static VOID RemPCIIntServer(APTR card, struct Interrupt *interrupt,
482 struct DevBase *base)
484 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
485 if(base->prometheus_base != NULL)
486 RemPrometheusIntServer(card, interrupt, base);
487 #endif
488 #ifdef __mc68000
489 if(base->powerpci_base != NULL)
490 RemPowerPCIIntServer(card, interrupt, base);
491 #endif
492 #ifdef __amigaos4__
493 if(base->expansion_base != NULL)
494 RemExpansionIntServer(card, interrupt, base);
495 #endif
496 #ifdef __MORPHOS__
497 if(base->openpci_base != NULL)
498 RemOpenPCIIntServer(card, interrupt, base);
499 #endif
501 return;
506 /****i* intelpro100.device/IsCardCompatible ********************************
508 * NAME
509 * IsCardCompatible
511 * SYNOPSIS
512 * compatible = IsCardCompatible(context)
514 * BOOL IsCardCompatible(struct BusContext *);
516 ****************************************************************************
520 BOOL IsCardCompatible(UWORD vendor_id, UWORD product_id,
521 struct DevBase *base)
523 BOOL compatible = FALSE;
524 const UWORD *p;
526 for(p = product_codes; p[0] != 0xffff; p += 2)
528 if(p[0] == vendor_id && p[1] == product_id)
529 compatible = TRUE;
532 return compatible;
537 /****i* intelpro100.device/ByteInHook **************************************
539 * NAME
540 * ByteInHook
542 * SYNOPSIS
543 * value = ByteInHook(context, offset)
545 * UBYTE ByteInHook(struct BusContext *, ULONG);
547 ****************************************************************************
551 static UBYTE ByteInHook(struct BusContext *context, ULONG offset)
553 return BYTEIN(context->io_base + offset);
558 /****i* intelpro100.device/ByteOutHook *************************************
560 * NAME
561 * ByteOutHook
563 * SYNOPSIS
564 * ByteOutHook(context, offset, value)
566 * VOID ByteOutHook(struct BusContext *, ULONG, UBYTE);
568 ****************************************************************************
572 static VOID ByteOutHook(struct BusContext *context, ULONG offset,
573 UBYTE value)
575 BYTEOUT(context->io_base + offset, value);
577 return;
582 /****i* intelpro100.device/LEWordInHook ************************************
584 * NAME
585 * LEWordInHook
587 * SYNOPSIS
588 * value = LEWordInHook(context, offset)
590 * UWORD LEWordInHook(struct BusContext *, ULONG);
592 ****************************************************************************
596 static UWORD LEWordInHook(struct BusContext *context, ULONG offset)
598 return LEWORDIN(context->io_base + offset);
603 /****i* intelpro100.device/LELongInHook ************************************
605 * NAME
606 * LELongInHook
608 * SYNOPSIS
609 * value = LELongInHook(context, offset)
611 * ULONG LELongInHook(struct BusContext *, ULONG);
613 ****************************************************************************
617 static ULONG LELongInHook(struct BusContext *context, ULONG offset)
619 return LELONGIN(context->io_base + offset);
624 /****i* intelpro100.device/LEWordOutHook ***********************************
626 * NAME
627 * LEWordOutHook
629 * SYNOPSIS
630 * LEWordOutHook(context, offset, value)
632 * VOID LEWordOutHook(struct BusContext *, ULONG, UWORD);
634 ****************************************************************************
638 static VOID LEWordOutHook(struct BusContext *context, ULONG offset,
639 UWORD value)
641 LEWORDOUT(context->io_base + offset, value);
643 return;
648 /****i* intelpro100.device/LELongOutHook ***********************************
650 * NAME
651 * LELongOutHook
653 * SYNOPSIS
654 * LELongOutHook(context, offset, value)
656 * VOID LELongOutHook(struct BusContext *, ULONG, ULONG);
658 ****************************************************************************
662 static VOID LELongOutHook(struct BusContext *context, ULONG offset,
663 ULONG value)
665 LELONGOUT(context->io_base + offset, value);
667 return;
672 /****i* intelpro100.device/AllocDMAMemHook *********************************
674 * NAME
675 * AllocDMAMemHook
677 * SYNOPSIS
678 * mem = AllocDMAMemHook(context, size, alignment)
680 * APTR AllocDMAMemHook(struct BusContext *, UPINT, UWORD);
682 ****************************************************************************
684 * Alignment currently must be minimum of 8 bytes.
688 static APTR AllocDMAMemHook(struct BusContext *context, UPINT size,
689 UWORD alignment)
691 struct DevBase *base;
692 APTR mem = NULL, original_mem;
694 base = context->device;
695 size += 2 * sizeof(APTR) + alignment;
696 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
697 if(base->prometheus_base != NULL)
698 original_mem = AllocPrometheusDMAMem(size, base);
699 else
700 #endif
701 original_mem = AllocMem(size, MEMF_PUBLIC);
702 if(original_mem != NULL)
704 mem = (APTR)((UPINT)(original_mem + 2 * sizeof(APTR) + alignment - 1)
705 & ~(alignment - 1));
706 *((APTR *)mem - 1) = original_mem;
707 *((UPINT *)mem - 2) = size;
710 return mem;
715 /****i* intelpro100.device/FreeDMAMemHook **********************************
717 * NAME
718 * FreeDMAMemHook
720 * SYNOPSIS
721 * FreeDMAMemHook(context, mem)
723 * VOID FreeDMAMemHook(struct BusContext *, APTR);
725 ****************************************************************************
729 static VOID FreeDMAMemHook(struct BusContext *context, APTR mem)
731 struct DevBase *base;
733 base = context->device;
734 if(mem != NULL)
736 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
737 if(base->prometheus_base != NULL)
738 FreePrometheusDMAMem(*((APTR *)mem - 1), *((UPINT *)mem - 2),
739 base);
740 else
741 #endif
742 FreeMem(*((APTR *)mem - 1), *((UPINT *)mem - 2));
745 return;
750 /****i* intelpro100.device/WrapInt *****************************************
752 * NAME
753 * WrapInt
755 ****************************************************************************
759 BOOL WrapInt(struct Interrupt *interrupt, struct DevBase *base)
761 BOOL success = TRUE;
762 #if defined(__amigaos4__) || defined(__MORPHOS__)
763 APTR *int_data;
765 int_data = AllocMem(2 * sizeof(APTR), MEMF_PUBLIC | MEMF_CLEAR);
766 if(int_data != NULL)
768 int_data[0] = interrupt->is_Code;
769 int_data[1] = interrupt->is_Data;
770 interrupt->is_Code = base->wrapper_int_code;
771 interrupt->is_Data = int_data;
773 else
774 success = FALSE;
775 #endif
777 return success;
782 /****i* intelpro100.device/UnwrapInt ***************************************
784 * NAME
785 * UnwrapInt
787 ****************************************************************************
791 static VOID UnwrapInt(struct Interrupt *interrupt, struct DevBase *base)
793 if(interrupt->is_Code == base->wrapper_int_code)
794 FreeMem(interrupt->is_Data, 2 * sizeof(APTR));
796 return;