revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / networks / etherlink3 / pci.c
blobbe404c601e51a576f1acfdbd13a6381d20c4e1cf
1 /*
3 Copyright (C) 2004-2011 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 "device_protos.h"
38 #include "prometheus_protos.h"
39 #include "powerpci_protos.h"
40 #include "expansion_protos.h"
41 #include "openpci_protos.h"
42 #include "unit_protos.h"
45 /* Private prototypes */
47 static struct DevUnit *FindPCIUnit(ULONG index, struct DevBase *base);
48 static struct DevUnit *CreatePCIUnit(ULONG index, struct DevBase *base);
49 static struct BusContext *AllocCard(ULONG index, struct DevBase *base);
50 static VOID FreeCard(struct BusContext *context, struct DevBase *base);
51 static BOOL AddPCIIntServer(APTR card, struct Interrupt *interrupt,
52 struct DevBase *base);
53 static VOID RemPCIIntServer(APTR card, struct Interrupt *interrupt,
54 struct DevBase *base);
55 static UBYTE ByteInHook(struct BusContext *context, ULONG offset);
56 static ULONG LongInHook(struct BusContext *context, ULONG offset);
57 static VOID ByteOutHook(struct BusContext *context, ULONG offset,
58 UBYTE value);
59 static VOID WordOutHook(struct BusContext *context, ULONG offset,
60 UWORD value);
61 static VOID LongOutHook(struct BusContext *context, ULONG offset,
62 ULONG value);
63 static VOID LongsInHook(struct BusContext *context, ULONG offset,
64 ULONG *buffer, ULONG count);
65 static VOID LongsOutHook(struct BusContext *context, ULONG offset,
66 const ULONG *buffer, ULONG count);
67 static VOID BEWordOutHook(struct BusContext *context, ULONG offset,
68 UWORD value);
69 static UWORD LEWordInHook(struct BusContext *context, ULONG offset);
70 static ULONG LELongInHook(struct BusContext *context, ULONG offset);
71 static VOID LEWordOutHook(struct BusContext *context, ULONG offset,
72 UWORD value);
73 static VOID LELongOutHook(struct BusContext *context, ULONG offset,
74 ULONG value);
75 static APTR AllocDMAMemHook(struct BusContext *context, UPINT size,
76 UWORD alignment);
77 static VOID FreeDMAMemHook(struct BusContext *context, APTR mem);
80 const UWORD product_codes[] =
82 0x10b7, 0x1201,
83 0x10b7, 0x1202,
84 0x10b7, 0x4500,
85 0x10b7, 0x5900,
86 0x10b7, 0x5950,
87 0x10b7, 0x5951,
88 0x10b7, 0x5952,
89 0x10b7, 0x9000,
90 0x10b7, 0x9001,
91 0x10b7, 0x9004,
92 0x10b7, 0x9005,
93 0x10b7, 0x9006,
94 0x10b7, 0x900A,
95 0x10b7, 0x9050,
96 0x10b7, 0x9051,
97 0x10b7, 0x9055,
98 0x10b7, 0x9056,
99 0x10b7, 0x9058,
100 0x10b7, 0x905A,
101 0x10b7, 0x9200,
102 0x10b7, 0x9201,
103 0x10b7, 0x9210,
104 0x10b7, 0x9800,
105 0x10b7, 0x9805,
106 0xffff, 0xffff
110 static const struct TagItem unit_tags[] =
112 {IOTAG_ByteIn, (UPINT)ByteInHook},
113 {IOTAG_LongIn, (UPINT)LongInHook},
114 {IOTAG_ByteOut, (UPINT)ByteOutHook},
115 {IOTAG_WordOut, (UPINT)WordOutHook},
116 {IOTAG_LongOut, (UPINT)LongOutHook},
117 {IOTAG_LongsIn, (UPINT)LongsInHook},
118 {IOTAG_LongsOut, (UPINT)LongsOutHook},
119 {IOTAG_BEWordOut, (UPINT)BEWordOutHook},
120 {IOTAG_LEWordIn, (UPINT)LEWordInHook},
121 {IOTAG_LELongIn, (UPINT)LELongInHook},
122 {IOTAG_LEWordOut, (UPINT)LEWordOutHook},
123 {IOTAG_LELongOut, (UPINT)LELongOutHook},
124 {IOTAG_AllocDMAMem, (UPINT)AllocDMAMemHook},
125 {IOTAG_FreeDMAMem, (UPINT)FreeDMAMemHook},
126 {TAG_END, 0}
130 /****i* etherlink3.device/GetPCICount **************************************
132 * NAME
133 * GetPCICount -- Get the number of compatible PCI Cards.
135 * SYNOPSIS
136 * count = GetPCICount()
138 * ULONG GetPCICount();
140 ****************************************************************************
144 ULONG GetPCICount(struct DevBase *base)
146 ULONG count = 0;
148 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
149 if(base->prometheus_base != NULL)
150 count = GetPrometheusCount(base);
151 #endif
152 #if defined(__mc68000__) && !defined(__AROS__)
153 if(base->powerpci_base != NULL)
154 count = GetPowerPCICount(base);
155 #endif
156 #ifdef __amigaos4__
157 if(base->expansion_base != NULL)
158 count = GetExpansionCount(base);
159 #endif
160 #ifdef __MORPHOS__
161 if(base->openpci_base != NULL)
162 count = GetOpenPCICount(base);
163 #endif
165 return count;
170 /****i* etherlink3.device/GetPCIUnit ***************************************
172 * NAME
173 * GetPCIUnit -- Get a unit by number.
175 * SYNOPSIS
176 * unit = GetPCIUnit(index)
178 * struct DevUnit *GetPCIUnit(ULONG);
180 ****************************************************************************
184 struct DevUnit *GetPCIUnit(ULONG index, struct DevBase *base)
186 struct DevUnit *unit;
188 unit = FindPCIUnit(index, base);
190 if(unit == NULL)
192 unit = CreatePCIUnit(index, base);
193 if(unit != NULL)
195 AddTail((APTR)&base->pci_units, (APTR)unit);
199 return unit;
204 /****i* etherlink3.device/FindPCIUnit **************************************
206 * NAME
207 * FindPCIUnit -- Find a unit by number.
209 * SYNOPSIS
210 * unit = FindPCIUnit(index)
212 * struct DevUnit *FindPCIUnit(ULONG);
214 ****************************************************************************
218 static struct DevUnit *FindPCIUnit(ULONG index, struct DevBase *base)
220 struct DevUnit *unit, *tail;
221 BOOL found = FALSE;
223 unit = (APTR)base->pci_units.mlh_Head;
224 tail = (APTR)&base->pci_units.mlh_Tail;
226 while(unit != tail && !found)
228 if(unit->index == index)
229 found = TRUE;
230 else
231 unit = (APTR)unit->node.mln_Succ;
234 if(!found)
235 unit = NULL;
237 return unit;
242 /****i* etherlink3.device/CreatePCIUnit ************************************
244 * NAME
245 * CreatePCIUnit -- Create a PCI unit.
247 * SYNOPSIS
248 * unit = CreatePCIUnit(index)
250 * struct DevUnit *CreatePCIUnit(ULONG);
252 * FUNCTION
253 * Creates a new PCI unit.
255 ****************************************************************************
259 static struct DevUnit *CreatePCIUnit(ULONG index, struct DevBase *base)
261 BOOL success = TRUE;
262 struct BusContext *context;
263 struct DevUnit *unit = NULL;
265 context = AllocCard(index, base);
266 if(context == NULL)
267 success = FALSE;
269 if(success)
271 if(context->unit_tags == NULL)
272 context->unit_tags = unit_tags;
273 context->device = base;
274 context->unit = unit = CreateUnit(index, context, context->unit_tags,
275 context->generation, PCI_BUS, base);
276 if(unit == NULL)
277 success = FALSE;
280 /* Add interrupt */
282 if(success)
284 if(!(WrapInt(&unit->status_int, base)
285 && WrapInt(&unit->rx_int, base)
286 && WrapInt(&unit->tx_int, base)
287 && WrapInt(&unit->tx_end_int, base)))
288 success = FALSE;
289 success = AddPCIIntServer(context->card, &unit->status_int, base);
292 if(!success)
294 if(context != NULL)
296 DeleteUnit(context->unit, base);
297 FreeCard(context, base);
299 unit = NULL;
302 return unit;
307 /****i* etherlink3.device/DeletePCIUnit ************************************
309 * NAME
310 * DeletePCIUnit -- Delete a unit.
312 * SYNOPSIS
313 * DeletePCIUnit(unit)
315 * VOID DeletePCIUnit(struct DevUnit *);
317 * FUNCTION
318 * Deletes a unit.
320 * INPUTS
321 * unit - Device unit (can be NULL).
323 * RESULT
324 * None.
326 ****************************************************************************
330 VOID DeletePCIUnit(struct DevUnit *unit, struct DevBase *base)
332 struct BusContext *context;
334 if(unit != NULL)
336 context = unit->card;
337 RemPCIIntServer(context->card, &unit->status_int, base);
338 UnwrapInt(&unit->tx_end_int, base);
339 UnwrapInt(&unit->tx_int, base);
340 UnwrapInt(&unit->rx_int, base);
341 UnwrapInt(&unit->status_int, base);
342 DeleteUnit(unit, base);
343 FreeCard(context, base);
346 return;
351 /****i* etherlink3.device/AllocCard ****************************************
353 * NAME
354 * AllocCard -- Get card from system.
356 * SYNOPSIS
357 * context = AllocCard(index)
359 * struct BusContext *AllocCard(ULONG);
361 ****************************************************************************
365 static struct BusContext *AllocCard(ULONG index, struct DevBase *base)
367 struct BusContext *context;
369 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
370 if(base->prometheus_base != NULL)
371 context = AllocPrometheusCard(index, base);
372 #endif
373 #if defined(__mc68000__) && !defined(__AROS__)
374 if(base->powerpci_base != NULL)
375 context = AllocPowerPCICard(index, base);
376 #endif
377 #ifdef __amigaos4__
378 if(base->expansion_base != NULL)
379 context = AllocExpansionCard(index, base);
380 #endif
381 #ifdef __MORPHOS__
382 if(base->openpci_base != NULL)
383 context = AllocOpenPCICard(index, base);
384 #endif
386 return context;
391 /****i* etherlink3.device/FreeCard *****************************************
393 * NAME
394 * FreeCard
396 * SYNOPSIS
397 * FreeCard(context)
399 * VOID FreeCard(struct BusContext *);
401 ****************************************************************************
405 static VOID FreeCard(struct BusContext *context, struct DevBase *base)
408 if(context != NULL)
410 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
411 if(base->prometheus_base != NULL)
412 FreePrometheusCard(context, base);
413 #endif
414 #if defined(__mc68000) && !defined(__AROS__)
415 if(base->powerpci_base != NULL)
416 FreePowerPCICard(context, base);
417 #endif
418 #ifdef __amigaos4__
419 if(base->expansion_base != NULL)
420 FreeExpansionCard(context, base);
421 #endif
422 #ifdef __MORPHOS__
423 if(base->openpci_base != NULL)
424 FreeOpenPCICard(context, base);
425 #endif
428 return;
433 /****i* etherlink3.device/AddPCIIntServer **********************************
435 * NAME
436 * AddPCIIntServer
438 * SYNOPSIS
439 * success = AddPCIIntServer(card, interrupt)
441 * BOOL AddPCIIntServer(APTR, struct Interrupt *);
443 ****************************************************************************
447 static BOOL AddPCIIntServer(APTR card, struct Interrupt *interrupt,
448 struct DevBase *base)
450 BOOL success;
452 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
453 if(base->prometheus_base != NULL)
454 success = AddPrometheusIntServer(card, interrupt, base);
455 #endif
456 #if defined(__mc68000) && !defined(__AROS__)
457 if(base->powerpci_base != NULL)
458 success = AddPowerPCIIntServer(card, interrupt, base);
459 #endif
460 #ifdef __amigaos4__
461 if(base->expansion_base != NULL)
462 success = AddExpansionIntServer(card, interrupt, base);
463 #endif
464 #ifdef __MORPHOS__
465 if(base->openpci_base != NULL)
466 success = AddOpenPCIIntServer(card, interrupt, base);
467 #endif
469 return success;
474 /****i* etherlink3.device/RemPCIIntServer **********************************
476 * NAME
477 * RemPCIIntServer
479 * SYNOPSIS
480 * RemPCIIntServer(card, interrupt)
482 * VOID RemPCIIntServer(APTR, struct Interrupt *);
484 ****************************************************************************
488 static VOID RemPCIIntServer(APTR card, struct Interrupt *interrupt,
489 struct DevBase *base)
491 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
492 if(base->prometheus_base != NULL)
493 RemPrometheusIntServer(card, interrupt, base);
494 #endif
495 #if defined(__mc68000) && !defined(__AROS__)
496 if(base->powerpci_base != NULL)
497 RemPowerPCIIntServer(card, interrupt, base);
498 #endif
499 #ifdef __amigaos4__
500 if(base->expansion_base != NULL)
501 RemExpansionIntServer(card, interrupt, base);
502 #endif
503 #ifdef __MORPHOS__
504 if(base->openpci_base != NULL)
505 RemOpenPCIIntServer(card, interrupt, base);
506 #endif
508 return;
513 /****i* etherlink3.device/IsCardCompatible *********************************
515 * NAME
516 * IsCardCompatible
518 * SYNOPSIS
519 * compatible = IsCardCompatible(vendor_id, product_id)
521 * BOOL IsCardCompatible(UWORD, UWORD);
523 ****************************************************************************
527 BOOL IsCardCompatible(UWORD vendor_id, UWORD product_id,
528 struct DevBase *base)
530 BOOL compatible = FALSE;
531 const UWORD *p;
533 for(p = product_codes; p[0] != 0xffff; p += 2)
535 if(p[0] == vendor_id && p[1] == product_id)
536 compatible = TRUE;
539 return compatible;
544 /****i* etherlink3.device/GetGeneration ************************************
546 * NAME
547 * GetGeneration
549 * SYNOPSIS
550 * generation = GetGeneration(product_id)
552 * UWORD GetGeneration(UWORD);
554 ****************************************************************************
558 UWORD GetGeneration(UWORD product_id, struct DevBase *base)
560 UWORD generation;
562 switch(product_id)
564 case 0x5900:
565 case 0x5950:
566 case 0x5951:
567 case 0x5952:
568 generation = VORTEX_GEN;
569 break;
570 case 0x9000:
571 case 0x9050:
572 case 0x9051:
573 generation = BOOMERANG_GEN;
574 break;
575 case 0x9004:
576 case 0x9005:
577 case 0x9006:
578 case 0x900a:
579 case 0x9055:
580 case 0x9056:
581 case 0x9058:
582 case 0x905a:
583 case 0x9800:
584 case 0x9805:
585 generation = CYCLONE_GEN;
586 break;
587 default:
588 generation = TORNADO_GEN;
591 return generation;
596 /****i* etherlink3.device/ByteInHook ***************************************
598 * NAME
599 * ByteInHook
601 * SYNOPSIS
602 * value = ByteInHook(context, offset)
604 * UBYTE ByteInHook(struct BusContext *, ULONG);
606 ****************************************************************************
610 static UBYTE ByteInHook(struct BusContext *context, ULONG offset)
612 return BYTEIN(context->io_base + offset);
617 /****i* etherlink3.device/LongInHook ***************************************
619 * NAME
620 * LongInHook
622 * SYNOPSIS
623 * value = LongInHook(context, offset)
625 * ULONG LongInHook(struct BusContext *, ULONG);
627 ****************************************************************************
631 static ULONG LongInHook(struct BusContext *context, ULONG offset)
633 return LONGIN(context->io_base + offset);
638 /****i* etherlink3.device/ByteOutHook **************************************
640 * NAME
641 * ByteOutHook
643 * SYNOPSIS
644 * ByteOutHook(context, offset, value)
646 * VOID ByteOutHook(struct BusContext *, ULONG, UBYTE);
648 ****************************************************************************
652 static VOID ByteOutHook(struct BusContext *context, ULONG offset,
653 UBYTE value)
655 BYTEOUT(context->io_base + offset, value);
657 return;
662 /****i* etherlink3.device/WordOutHook **************************************
664 * NAME
665 * WordOutHook
667 * SYNOPSIS
668 * WordOutHook(context, offset, value)
670 * VOID WordOutHook(struct BusContext *, ULONG, UWORD);
672 ****************************************************************************
676 static VOID WordOutHook(struct BusContext *context, ULONG offset,
677 UWORD value)
679 WORDOUT(context->io_base + offset, value);
681 return;
686 /****i* etherlink3.device/LongOutHook **************************************
688 * NAME
689 * LongOutHook
691 * SYNOPSIS
692 * LongOutHook(context, offset, value)
694 * VOID LongOutHook(struct BusContext *, ULONG, ULONG);
696 ****************************************************************************
700 static VOID LongOutHook(struct BusContext *context, ULONG offset,
701 ULONG value)
703 LONGOUT(context->io_base + offset, value);
705 return;
710 /****i* etherlink3.device/LongsInHook **************************************
712 * NAME
713 * LongsInHook
715 * SYNOPSIS
716 * LongsInHook(context, offset, buffer, count)
718 * VOID LongsInHook(struct BusContext *, ULONG, ULONG *, ULONG);
720 ****************************************************************************
724 static VOID LongsInHook(struct BusContext *context, ULONG offset,
725 ULONG *buffer, ULONG count)
727 LONGSIN(context->io_base + offset, buffer, count);
729 return;
734 /****i* etherlink3.device/LongsOutHook *************************************
736 * NAME
737 * LongsOutHook
739 * SYNOPSIS
740 * LongsOutHook(context, offset, buffer, count)
742 * VOID LongsOutHook(struct BusContext *, ULONG, const ULONG *, ULONG);
744 ****************************************************************************
748 static VOID LongsOutHook(struct BusContext *context, ULONG offset,
749 const ULONG *buffer, ULONG count)
751 LONGSOUT(context->io_base + offset, buffer, count);
753 return;
758 /****i* etherlink3.device/BEWordOutHook ************************************
760 * NAME
761 * BEWordOutHook
763 * SYNOPSIS
764 * BEWordOutHook(context, offset, value)
766 * VOID BEWordOutHook(struct BusContext *, ULONG, UWORD);
768 ****************************************************************************
772 static VOID BEWordOutHook(struct BusContext *context, ULONG offset,
773 UWORD value)
775 BEWORDOUT(context->io_base + offset, value);
777 return;
782 /****i* etherlink3.device/LEWordInHook *************************************
784 * NAME
785 * LEWordInHook
787 * SYNOPSIS
788 * value = LEWordInHook(context, offset)
790 * UWORD LEWordInHook(struct BusContext *, ULONG);
792 ****************************************************************************
796 static UWORD LEWordInHook(struct BusContext *context, ULONG offset)
798 return LEWORDIN(context->io_base + offset);
803 /****i* etherlink3.device/LELongInHook *************************************
805 * NAME
806 * LELongInHook
808 * SYNOPSIS
809 * value = LELongInHook(context, offset)
811 * ULONG LELongInHook(struct BusContext *, ULONG);
813 ****************************************************************************
817 static ULONG LELongInHook(struct BusContext *context, ULONG offset)
819 return LELONGIN(context->io_base + offset);
824 /****i* etherlink3.device/LEWordOutHook ************************************
826 * NAME
827 * LEWordOutHook
829 * SYNOPSIS
830 * LEWordOutHook(context, offset, value)
832 * VOID LEWordOutHook(struct BusContext *, ULONG, UWORD);
834 ****************************************************************************
838 static VOID LEWordOutHook(struct BusContext *context, ULONG offset,
839 UWORD value)
841 LEWORDOUT(context->io_base + offset, value);
843 return;
848 /****i* etherlink3.device/LELongOutHook ************************************
850 * NAME
851 * LELongOutHook
853 * SYNOPSIS
854 * LELongOutHook(context, offset, value)
856 * VOID LELongOutHook(struct BusContext *, ULONG, ULONG);
858 ****************************************************************************
862 static VOID LELongOutHook(struct BusContext *context, ULONG offset,
863 ULONG value)
865 LELONGOUT(context->io_base + offset, value);
867 return;
872 /****i* etherlink3.device/AllocDMAMemHook **********************************
874 * NAME
875 * AllocDMAMemHook
877 * SYNOPSIS
878 * mem = AllocDMAMemHook(context, size, alignment)
880 * APTR AllocDMAMemHook(struct BusContext *, UPINT, UWORD);
882 ****************************************************************************
884 * Alignment currently must be minimum of 8 bytes.
888 static APTR AllocDMAMemHook(struct BusContext *context, UPINT size,
889 UWORD alignment)
891 struct DevBase *base;
892 APTR mem = NULL, original_mem;
894 base = context->device;
895 size += 2 * sizeof(APTR) + alignment;
896 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
897 if(base->prometheus_base != NULL)
898 original_mem = AllocPrometheusDMAMem(size, base);
899 else
900 #endif
901 original_mem = AllocMem(size, MEMF_PUBLIC);
902 if(original_mem != NULL)
904 mem = (APTR)((UPINT)(original_mem + 2 * sizeof(APTR) + alignment - 1)
905 & ~(alignment - 1));
906 *((APTR *)mem - 1) = original_mem;
907 *((UPINT *)mem - 2) = size;
910 return mem;
915 /****i* etherlink3.device/FreeDMAMemHook ***********************************
917 * NAME
918 * FreeDMAMemHook
920 * SYNOPSIS
921 * FreeDMAMemHook(context, mem)
923 * VOID FreeDMAMemHook(struct BusContext *, APTR);
925 ****************************************************************************
929 static VOID FreeDMAMemHook(struct BusContext *context, APTR mem)
931 struct DevBase *base;
933 base = context->device;
934 if(mem != NULL)
936 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
937 if(base->prometheus_base != NULL)
938 FreePrometheusDMAMem(*((APTR *)mem - 1), *((UPINT *)mem - 2),
939 base);
940 else
941 #endif
942 FreeMem(*((APTR *)mem - 1), *((UPINT *)mem - 2));
945 return;