Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / devs / networks / intelpro100 / pci.c
blob0c384ea660ccfc42cac38543db52150e622c52b1
1 /*
3 Copyright (C) 2004-2009 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, 0x1051,
90 0x8086, 0x1052,
91 0x8086, 0x1053,
92 0x8086, 0x1054,
93 0x8086, 0x1055,
94 0x8086, 0x1056,
95 0x8086, 0x1057,
96 0x8086, 0x1059,
97 0x8086, 0x1064,
98 0x8086, 0x1065,
99 0x8086, 0x1066,
100 0x8086, 0x1067,
101 0x8086, 0x1068,
102 0x8086, 0x1069,
103 0x8086, 0x106A,
104 0x8086, 0x106B,
105 0x8086, 0x1091,
106 0x8086, 0x1092,
107 0x8086, 0x1093,
108 0x8086, 0x1094,
109 0x8086, 0x1095,
110 0x8086, 0x1209,
111 0x8086, 0x1227,
112 0x8086, 0x1228,
113 0x8086, 0x1229,
114 0x8086, 0x2449,
115 0x8086, 0x2459,
116 0x8086, 0x245D,
117 0x8086, 0x27DC,
118 0x8086, 0x5200,
119 0x8086, 0x5201,
120 0xffff, 0xffff
124 static struct TagItem unit_tags[] =
126 {IOTAG_ByteIn, (UPINT)ByteInHook},
127 {IOTAG_ByteOut, (UPINT)ByteOutHook},
128 {IOTAG_LEWordIn, (UPINT)LEWordInHook},
129 {IOTAG_LELongIn, (UPINT)LELongInHook},
130 {IOTAG_LEWordOut, (UPINT)LEWordOutHook},
131 {IOTAG_LELongOut, (UPINT)LELongOutHook},
132 {IOTAG_AllocDMAMem, (UPINT)AllocDMAMemHook},
133 {IOTAG_FreeDMAMem, (UPINT)FreeDMAMemHook},
134 {TAG_END, 0}
138 /****i* intelpro100.device/GetPCICount *************************************
140 * NAME
141 * GetPCICount -- Get the number of compatible PCI Cards.
143 * SYNOPSIS
144 * count = GetPCICount()
146 * ULONG GetPCICount();
148 ****************************************************************************
152 ULONG GetPCICount(struct DevBase *base)
154 ULONG count = 0;
156 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
157 if(base->prometheus_base != NULL)
158 count = GetPrometheusCount(base);
159 #endif
160 #if defined(__mc68000__) && !defined(__AROS__)
161 if(base->powerpci_base != NULL)
162 count = GetPowerPCICount(base);
163 #endif
164 #ifdef __amigaos4__
165 if(base->expansion_base != NULL)
166 count = GetExpansionCount(base);
167 #endif
168 #ifdef __MORPHOS__
169 if(base->openpci_base != NULL)
170 count = GetOpenPCICount(base);
171 #endif
173 return count;
178 /****i* intelpro100.device/GetPCIUnit **************************************
180 * NAME
181 * GetPCIUnit -- Get a unit by number.
183 * SYNOPSIS
184 * unit = GetPCIUnit(index)
186 * struct DevUnit *GetPCIUnit(ULONG);
188 ****************************************************************************
192 struct DevUnit *GetPCIUnit(ULONG index, struct DevBase *base)
194 struct DevUnit *unit;
196 unit = FindPCIUnit(index, base);
198 if(unit == NULL)
200 unit = CreatePCIUnit(index, base);
201 if(unit != NULL)
203 AddTail((APTR)&base->pci_units, (APTR)unit);
207 return unit;
212 /****i* intelpro100.device/FindPCIUnit *************************************
214 * NAME
215 * FindPCIUnit -- Find a unit by number.
217 * SYNOPSIS
218 * unit = FindPCIUnit(index)
220 * struct DevUnit *FindPCIUnit(ULONG);
222 ****************************************************************************
226 static struct DevUnit *FindPCIUnit(ULONG index, struct DevBase *base)
228 struct DevUnit *unit, *tail;
229 BOOL found = FALSE;
231 unit = (APTR)base->pci_units.mlh_Head;
232 tail = (APTR)&base->pci_units.mlh_Tail;
234 while(unit != tail && !found)
236 if(unit->index == index)
237 found = TRUE;
238 else
239 unit = (APTR)unit->node.mln_Succ;
242 if(!found)
243 unit = NULL;
245 return unit;
250 /****i* intelpro100.device/CreatePCIUnit ***********************************
252 * NAME
253 * CreatePCIUnit -- Create a unit.
255 * SYNOPSIS
256 * unit = CreatePCIUnit(index)
258 * struct DevUnit *CreatePCIUnit(ULONG);
260 * FUNCTION
261 * Creates a PCI new unit.
263 ****************************************************************************
267 static struct DevUnit *CreatePCIUnit(ULONG index, struct DevBase *base)
269 BOOL success = TRUE;
270 struct BusContext *context;
271 struct DevUnit *unit = NULL;
273 context = AllocCard(index, base);
274 if(context == NULL)
275 success = FALSE;
277 if(success)
279 if(context->unit_tags == NULL)
281 context->unit_tags = unit_tags;
285 if(success)
287 context->device = base;
288 context->unit = unit =
289 CreateUnit(index, context, context->unit_tags, PCI_BUS, base);
290 if(unit == NULL)
291 success = FALSE;
294 /* Add interrupt */
296 if(success)
298 if(!(WrapInt(&unit->status_int, base)
299 && WrapInt(&unit->rx_int, base)
300 && WrapInt(&unit->tx_int, base)
301 && WrapInt(&unit->tx_end_int, base)))
302 success = FALSE;
303 success = AddPCIIntServer(context->card, &unit->status_int, base);
306 if(!success)
308 if(context != NULL)
310 DeleteUnit(context->unit, base);
311 FreeCard(context, base);
313 unit = NULL;
316 return unit;
321 /****i* intelpro100.device/DeletePCIUnit ***********************************
323 * NAME
324 * DeletePCIUnit -- Delete a unit.
326 * SYNOPSIS
327 * DeletePCIUnit(unit)
329 * VOID DeletePCIUnit(struct DevUnit *);
331 * FUNCTION
332 * Deletes a unit.
334 * INPUTS
335 * unit - Device unit (can be NULL).
337 * RESULT
338 * None.
340 ****************************************************************************
344 VOID DeletePCIUnit(struct DevUnit *unit, struct DevBase *base)
346 struct BusContext *context;
348 if(unit != NULL)
350 context = unit->card;
351 RemPCIIntServer(context->card, &unit->status_int, base);
352 UnwrapInt(&unit->tx_end_int, base);
353 UnwrapInt(&unit->tx_int, base);
354 UnwrapInt(&unit->rx_int, base);
355 UnwrapInt(&unit->status_int, base);
356 DeleteUnit(unit, base);
357 FreeCard(context, base);
360 return;
365 /****i* intelpro100.device/AllocCard ***************************************
367 * NAME
368 * AllocCard -- Get card from system.
370 * SYNOPSIS
371 * context = AllocCard(index)
373 * struct BusContext *AllocCard(ULONG);
375 ****************************************************************************
379 static struct BusContext *AllocCard(ULONG index, struct DevBase *base)
381 struct BusContext *context;
383 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
384 if(base->prometheus_base != NULL)
385 context = AllocPrometheusCard(index, base);
386 #endif
387 #if defined(__mc68000__) && !defined(__AROS__)
388 if(base->powerpci_base != NULL)
389 context = AllocPowerPCICard(index, base);
390 #endif
391 #ifdef __amigaos4__
392 if(base->expansion_base != NULL)
393 context = AllocExpansionCard(index, base);
394 #endif
395 #ifdef __MORPHOS__
396 if(base->openpci_base != NULL)
397 context = AllocOpenPCICard(index, base);
398 #endif
400 return context;
405 /****i* intelpro100.device/FreeCard ****************************************
407 * NAME
408 * FreeCard
410 * SYNOPSIS
411 * FreeCard(context)
413 * VOID FreeCard(struct BusContext *);
415 ****************************************************************************
419 static VOID FreeCard(struct BusContext *context, struct DevBase *base)
422 if(context != NULL)
424 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
425 if(base->prometheus_base != NULL)
426 FreePrometheusCard(context, base);
427 #endif
428 #if defined(__mc68000__) && !defined(__AROS__)
429 if(base->powerpci_base != NULL)
430 FreePowerPCICard(context, base);
431 #endif
432 #ifdef __amigaos4__
433 if(base->expansion_base != NULL)
434 FreeExpansionCard(context, base);
435 #endif
436 #ifdef __MORPHOS__
437 if(base->openpci_base != NULL)
438 FreeOpenPCICard(context, base);
439 #endif
442 return;
447 /****i* intelpro100.device/AddPCIIntServer *********************************
449 * NAME
450 * AddPCIIntServer
452 * SYNOPSIS
453 * context = AddPCIIntServer(index)
455 * struct BusContext *AddPCIIntServer(ULONG);
457 ****************************************************************************
461 static BOOL AddPCIIntServer(APTR card, struct Interrupt *interrupt,
462 struct DevBase *base)
464 BOOL success;
466 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
467 if(base->prometheus_base != NULL)
468 success = AddPrometheusIntServer(card, interrupt, base);
469 #endif
470 #if defined(__mc68000__) && !defined(__AROS__)
471 if(base->powerpci_base != NULL)
472 success = AddPowerPCIIntServer(card, interrupt, base);
473 #endif
474 #ifdef __amigaos4__
475 if(base->expansion_base != NULL)
476 success = AddExpansionIntServer(card, interrupt, base);
477 #endif
478 #ifdef __MORPHOS__
479 if(base->openpci_base != NULL)
480 success = AddOpenPCIIntServer(card, interrupt, base);
481 #endif
483 return success;
488 /****i* intelpro100.device/RemPCIIntServer *********************************
490 * NAME
491 * RemPCIIntServer
493 * SYNOPSIS
494 * RemPCIIntServer()
496 * VOID RemPCIIntServer(ULONG);
498 ****************************************************************************
502 static VOID RemPCIIntServer(APTR card, struct Interrupt *interrupt,
503 struct DevBase *base)
505 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
506 if(base->prometheus_base != NULL)
507 RemPrometheusIntServer(card, interrupt, base);
508 #endif
509 #if defined(__mc68000__) && !defined(__AROS__)
510 if(base->powerpci_base != NULL)
511 RemPowerPCIIntServer(card, interrupt, base);
512 #endif
513 #ifdef __amigaos4__
514 if(base->expansion_base != NULL)
515 RemExpansionIntServer(card, interrupt, base);
516 #endif
517 #ifdef __MORPHOS__
518 if(base->openpci_base != NULL)
519 RemOpenPCIIntServer(card, interrupt, base);
520 #endif
522 return;
527 /****i* intelpro100.device/IsCardCompatible ********************************
529 * NAME
530 * IsCardCompatible
532 * SYNOPSIS
533 * compatible = IsCardCompatible(context)
535 * BOOL IsCardCompatible(struct BusContext *);
537 ****************************************************************************
541 BOOL IsCardCompatible(UWORD vendor_id, UWORD product_id,
542 struct DevBase *base)
544 BOOL compatible = FALSE;
545 const UWORD *p;
547 for(p = product_codes; p[0] != 0xffff; p += 2)
549 if(p[0] == vendor_id && p[1] == product_id)
550 compatible = TRUE;
553 return compatible;
558 /****i* intelpro100.device/ByteInHook **************************************
560 * NAME
561 * ByteInHook
563 * SYNOPSIS
564 * value = ByteInHook(context, offset)
566 * UBYTE ByteInHook(struct BusContext *, ULONG);
568 ****************************************************************************
572 static UBYTE ByteInHook(struct BusContext *context, ULONG offset)
574 return BYTEIN(context->io_base + offset);
579 /****i* intelpro100.device/ByteOutHook *************************************
581 * NAME
582 * ByteOutHook
584 * SYNOPSIS
585 * ByteOutHook(context, offset, value)
587 * VOID ByteOutHook(struct BusContext *, ULONG, UBYTE);
589 ****************************************************************************
593 static VOID ByteOutHook(struct BusContext *context, ULONG offset,
594 UBYTE value)
596 BYTEOUT(context->io_base + offset, value);
598 return;
603 /****i* intelpro100.device/LEWordInHook ************************************
605 * NAME
606 * LEWordInHook
608 * SYNOPSIS
609 * value = LEWordInHook(context, offset)
611 * UWORD LEWordInHook(struct BusContext *, ULONG);
613 ****************************************************************************
617 static UWORD LEWordInHook(struct BusContext *context, ULONG offset)
619 return LEWORDIN(context->io_base + offset);
624 /****i* intelpro100.device/LELongInHook ************************************
626 * NAME
627 * LELongInHook
629 * SYNOPSIS
630 * value = LELongInHook(context, offset)
632 * ULONG LELongInHook(struct BusContext *, ULONG);
634 ****************************************************************************
638 static ULONG LELongInHook(struct BusContext *context, ULONG offset)
640 return LELONGIN(context->io_base + offset);
645 /****i* intelpro100.device/LEWordOutHook ***********************************
647 * NAME
648 * LEWordOutHook
650 * SYNOPSIS
651 * LEWordOutHook(context, offset, value)
653 * VOID LEWordOutHook(struct BusContext *, ULONG, UWORD);
655 ****************************************************************************
659 static VOID LEWordOutHook(struct BusContext *context, ULONG offset,
660 UWORD value)
662 LEWORDOUT(context->io_base + offset, value);
664 return;
669 /****i* intelpro100.device/LELongOutHook ***********************************
671 * NAME
672 * LELongOutHook
674 * SYNOPSIS
675 * LELongOutHook(context, offset, value)
677 * VOID LELongOutHook(struct BusContext *, ULONG, ULONG);
679 ****************************************************************************
683 static VOID LELongOutHook(struct BusContext *context, ULONG offset,
684 ULONG value)
686 LELONGOUT(context->io_base + offset, value);
688 return;
693 /****i* intelpro100.device/AllocDMAMemHook *********************************
695 * NAME
696 * AllocDMAMemHook
698 * SYNOPSIS
699 * mem = AllocDMAMemHook(context, size, alignment)
701 * APTR AllocDMAMemHook(struct BusContext *, UPINT, UWORD);
703 ****************************************************************************
705 * Alignment currently must be minimum of 8 bytes.
709 static APTR AllocDMAMemHook(struct BusContext *context, UPINT size,
710 UWORD alignment)
712 struct DevBase *base;
713 APTR mem = NULL, original_mem;
715 base = context->device;
716 size += 2 * sizeof(APTR) + alignment;
717 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
718 if(base->prometheus_base != NULL)
719 original_mem = AllocPrometheusDMAMem(size, base);
720 else
721 #endif
722 original_mem = AllocMem(size, MEMF_PUBLIC);
723 if(original_mem != NULL)
725 mem = (APTR)((UPINT)(original_mem + 2 * sizeof(APTR) + alignment - 1)
726 & ~(alignment - 1));
727 *((APTR *)mem - 1) = original_mem;
728 *((UPINT *)mem - 2) = size;
731 return mem;
736 /****i* intelpro100.device/FreeDMAMemHook **********************************
738 * NAME
739 * FreeDMAMemHook
741 * SYNOPSIS
742 * FreeDMAMemHook(context, mem)
744 * VOID FreeDMAMemHook(struct BusContext *, APTR);
746 ****************************************************************************
750 static VOID FreeDMAMemHook(struct BusContext *context, APTR mem)
752 struct DevBase *base;
754 base = context->device;
755 if(mem != NULL)
757 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
758 if(base->prometheus_base != NULL)
759 FreePrometheusDMAMem(*((APTR *)mem - 1), *((UPINT *)mem - 2),
760 base);
761 else
762 #endif
763 FreeMem(*((APTR *)mem - 1), *((UPINT *)mem - 2));
766 return;
771 /****i* intelpro100.device/WrapInt *****************************************
773 * NAME
774 * WrapInt
776 ****************************************************************************
780 BOOL WrapInt(struct Interrupt *interrupt, struct DevBase *base)
782 BOOL success = TRUE;
783 #if defined(__amigaos4__) || defined(__MORPHOS__)
784 APTR *int_data;
786 int_data = AllocMem(2 * sizeof(APTR), MEMF_PUBLIC | MEMF_CLEAR);
787 if(int_data != NULL)
789 int_data[0] = interrupt->is_Code;
790 int_data[1] = interrupt->is_Data;
791 interrupt->is_Code = base->wrapper_int_code;
792 interrupt->is_Data = int_data;
794 else
795 success = FALSE;
796 #endif
798 return success;
803 /****i* intelpro100.device/UnwrapInt ***************************************
805 * NAME
806 * UnwrapInt
808 ****************************************************************************
812 static VOID UnwrapInt(struct Interrupt *interrupt, struct DevBase *base)
814 if(interrupt->is_Code == base->wrapper_int_code)
815 FreeMem(interrupt->is_Data, 2 * sizeof(APTR));
817 return;