AHI: build Alsa driver when alsa-bridge link lib is detected
[AROS.git] / workbench / devs / networks / prism2 / pci.c
blobc7d45d22f8127f65dbc1a04665129f4dd8fcb77f
1 /*
3 Copyright (C) 2004-2012 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 #include <proto/exec.h>
27 #include <proto/expansion.h>
29 #include "device.h"
30 #include "pci.h"
32 #include "pci_protos.h"
33 #include "device_protos.h"
34 #include "prometheus_protos.h"
35 #include "powerpci_protos.h"
36 #include "cybpci_protos.h"
37 #include "expansion_protos.h"
38 #include "openpci_protos.h"
39 #include "unit_protos.h"
42 /* Private prototypes */
44 static struct DevUnit *FindPCIUnit(ULONG index, struct DevBase *base);
45 static struct DevUnit *CreatePCIUnit(ULONG index, struct DevBase *base);
46 static struct BusContext *AllocCard(ULONG index, struct DevBase *base);
47 static VOID FreeCard(struct BusContext *context, struct DevBase *base);
48 static BOOL AddPCIIntServer(APTR card, struct Interrupt *interrupt,
49 struct DevBase *base);
50 static VOID RemPCIIntServer(APTR card, struct Interrupt *interrupt,
51 struct DevBase *base);
52 BOOL IsCardCompatible(UWORD vendor_id, UWORD product_id,
53 struct DevBase *base);
54 static VOID WordsInHook(struct BusContext *context, ULONG offset,
55 UWORD *buffer, ULONG count);
56 static VOID WordsOutHook(struct BusContext *context, ULONG offset,
57 const UWORD *buffer, ULONG count);
58 static VOID BEWordOutHook(struct BusContext *context, ULONG offset,
59 UWORD value);
60 static UWORD LEWordInHook(struct BusContext *context, ULONG offset);
61 static VOID LEWordOutHook(struct BusContext *context, ULONG offset,
62 UWORD value);
63 static VOID WordsInIOHook(struct BusContext *context, ULONG offset,
64 UWORD *buffer, ULONG count);
65 static VOID WordsOutIOHook(struct BusContext *context, ULONG offset,
66 const UWORD *buffer, ULONG count);
67 static VOID BEWordOutIOHook(struct BusContext *context, ULONG offset,
68 UWORD value);
69 static UWORD LEWordInIOHook(struct BusContext *context, ULONG offset);
70 static VOID LEWordOutIOHook(struct BusContext *context, ULONG offset,
71 UWORD value);
74 const UWORD product_codes[] =
76 0x10b7, 0x7770,
77 0x111a, 0x1023,
78 0x1260, 0x3872,
79 0x1260, 0x3873,
80 0x1385, 0x4100,
81 0x15e8, 0x0130,
82 0x15e8, 0x0131,
83 0x1638, 0x1100,
84 0x16ab, 0x1100,
85 0x16ab, 0x1101,
86 0x16ab, 0x1102,
87 0x16ec, 0x3685,
88 0xec80, 0xec00,
89 0xffff, 0xffff
93 static struct TagItem unit_tags[] =
95 {IOTAG_WordsIn, (UPINT)WordsInHook},
96 {IOTAG_WordsOut, (UPINT)WordsOutHook},
97 {IOTAG_BEWordOut, (UPINT)BEWordOutHook},
98 {IOTAG_LEWordIn, (UPINT)LEWordInHook},
99 {IOTAG_LEWordOut, (UPINT)LEWordOutHook},
100 {TAG_END, 0}
104 static struct TagItem bridge_unit_tags[] =
106 {IOTAG_WordsIn, (UPINT)WordsInIOHook},
107 {IOTAG_WordsOut, (UPINT)WordsOutIOHook},
108 {IOTAG_BEWordOut, (UPINT)BEWordOutIOHook},
109 {IOTAG_LEWordIn, (UPINT)LEWordInIOHook},
110 {IOTAG_LEWordOut, (UPINT)LEWordOutIOHook},
111 {TAG_END, 0}
115 /****i* prism2.device/GetPCICount ******************************************
117 * NAME
118 * GetPCICount -- Get the number of compatible PCI Cards.
120 * SYNOPSIS
121 * count = GetPCICount()
123 * ULONG GetPCICount();
125 ****************************************************************************
129 ULONG GetPCICount(struct DevBase *base)
131 ULONG count = 0;
133 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
134 if(base->prometheus_base != NULL)
135 count = GetPrometheusCount(base);
136 #endif
137 #if defined(__mc68000) && !defined(__AROS__)
138 if(base->powerpci_base != NULL)
139 count = GetPowerPCICount(base);
140 if(base->cybpci_base != NULL)
141 count = GetCybPCICount(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* prism2.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* prism2.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* prism2.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 if(context->bus_type == PCI_BUS)
261 context->unit_tags = unit_tags;
262 else
263 context->unit_tags = bridge_unit_tags;
266 context->unit = unit =
267 CreateUnit(index, context, context->unit_tags, context->bus_type,
268 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->info_int, base)
281 && WrapInt(&unit->reset_handler, base)))
282 success = FALSE;
285 /* Add hardware interrupt and reset handler */
287 if(success)
289 if(AddPCIIntServer(context->card, &unit->status_int, base))
290 unit->flags |= UNITF_INTADDED;
291 else
292 success = FALSE;
294 #if defined(__amigaos4__) || defined(__AROS__)
295 if(AddResetCallback(&unit->reset_handler))
296 unit->flags |= UNITF_RESETADDED;
297 else
298 success = FALSE;
299 #endif
302 if(!success)
304 if(context != NULL)
306 DeleteUnit(context->unit, base);
307 FreeCard(context, base);
309 unit = NULL;
312 return unit;
317 /****i* prism2.device/DeletePCIUnit ****************************************
319 * NAME
320 * DeletePCIUnit -- Delete a unit.
322 * SYNOPSIS
323 * DeletePCIUnit(unit)
325 * VOID DeletePCIUnit(struct DevUnit *);
327 * FUNCTION
328 * Deletes a unit.
330 * INPUTS
331 * unit - Device unit (can be NULL).
333 * RESULT
334 * None.
336 ****************************************************************************
340 VOID DeletePCIUnit(struct DevUnit *unit, struct DevBase *base)
342 struct BusContext *context;
344 if(unit != NULL)
346 context = unit->card;
347 #if defined(__amigaos4__) || defined(__AROS__)
348 if((unit->flags & UNITF_RESETADDED) != 0)
349 RemResetCallback(&unit->reset_handler);
350 #endif
351 if((unit->flags & UNITF_INTADDED) != 0)
352 RemPCIIntServer(context->card, &unit->status_int, base);
353 UnwrapInt(&unit->reset_handler, base);
354 UnwrapInt(&unit->info_int, base);
355 UnwrapInt(&unit->tx_int, base);
356 UnwrapInt(&unit->rx_int, base);
357 UnwrapInt(&unit->status_int, base);
358 DeleteUnit(unit, base);
359 FreeCard(context, base);
362 return;
367 /****i* prism2.device/AllocCard ********************************************
369 * NAME
370 * AllocCard -- Get card from system.
372 * SYNOPSIS
373 * context = AllocCard(index)
375 * struct BusContext *AllocCard(ULONG);
377 ****************************************************************************
381 static struct BusContext *AllocCard(ULONG index, struct DevBase *base)
383 struct BusContext *context;
385 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
386 if(base->prometheus_base != NULL)
387 context = AllocPrometheusCard(index, base);
388 #endif
389 #if defined(__mc68000) && !defined(__AROS__)
390 if(base->powerpci_base != NULL)
391 context = AllocPowerPCICard(index, base);
392 if(base->cybpci_base != NULL)
393 context = AllocCybPCICard(index, base);
394 #endif
395 #ifdef __amigaos4__
396 if(base->expansion_base != NULL)
397 context = AllocExpansionCard(index, base);
398 #endif
399 #ifdef __MORPHOS__
400 if(base->openpci_base != NULL)
401 context = AllocOpenPCICard(index, base);
402 #endif
404 return context;
409 /****i* prism2.device/FreeCard *********************************************
411 * NAME
412 * FreeCard
414 * SYNOPSIS
415 * FreeCard(context)
417 * VOID FreeCard(struct BusContext *);
419 ****************************************************************************
423 static VOID FreeCard(struct BusContext *context, struct DevBase *base)
426 if(context != NULL)
428 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
429 if(base->prometheus_base != NULL)
430 FreePrometheusCard(context, base);
431 #endif
432 #if defined(__mc68000) && !defined(__AROS__)
433 if(base->powerpci_base != NULL)
434 FreePowerPCICard(context, base);
435 if(base->cybpci_base != NULL)
436 FreeCybPCICard(context, base);
437 #endif
438 #ifdef __amigaos4__
439 if(base->expansion_base != NULL)
440 FreeExpansionCard(context, base);
441 #endif
442 #ifdef __MORPHOS__
443 if(base->openpci_base != NULL)
444 FreeOpenPCICard(context, base);
445 #endif
448 return;
453 /****i* prism2.device/AddPCIIntServer **************************************
455 * NAME
456 * AddPCIIntServer
458 * SYNOPSIS
459 * success = AddPCIIntServer(card, interrupt)
461 * BOOL AddPCIIntServer(APTR, struct Interrupt *);
463 ****************************************************************************
467 static BOOL AddPCIIntServer(APTR card, struct Interrupt *interrupt,
468 struct DevBase *base)
470 BOOL success;
472 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
473 if(base->prometheus_base != NULL)
474 success = AddPrometheusIntServer(card, interrupt, base);
475 #endif
476 #if defined(__mc68000) && !defined(__AROS__)
477 if(base->powerpci_base != NULL)
478 success = AddPowerPCIIntServer(card, interrupt, base);
479 if(base->cybpci_base != NULL)
480 success = AddCybPCIIntServer(card, interrupt, base);
481 #endif
482 #ifdef __amigaos4__
483 if(base->expansion_base != NULL)
484 success = AddExpansionIntServer(card, interrupt, base);
485 #endif
486 #ifdef __MORPHOS__
487 if(base->openpci_base != NULL)
488 success = AddOpenPCIIntServer(card, interrupt, base);
489 #endif
491 return success;
496 /****i* prism2.device/RemPCIIntServer **************************************
498 * NAME
499 * RemPCIIntServer
501 * SYNOPSIS
502 * RemPCIIntServer(card, interrupt)
504 * VOID RemPCIIntServer(APTR, struct Interrupt *);
506 ****************************************************************************
510 static VOID RemPCIIntServer(APTR card, struct Interrupt *interrupt,
511 struct DevBase *base)
513 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
514 if(base->prometheus_base != NULL)
515 RemPrometheusIntServer(card, interrupt, base);
516 #endif
517 #if defined(__mc68000) && !defined(__AROS__)
518 if(base->powerpci_base != NULL)
519 RemPowerPCIIntServer(card, interrupt, base);
520 if(base->cybpci_base != NULL)
521 RemCybPCIIntServer(card, interrupt, base);
522 #endif
523 #ifdef __amigaos4__
524 if(base->expansion_base != NULL)
525 RemExpansionIntServer(card, interrupt, base);
526 #endif
527 #ifdef __MORPHOS__
528 if(base->openpci_base != NULL)
529 RemOpenPCIIntServer(card, interrupt, base);
530 #endif
532 return;
537 /****i* prism2.device/IsCardCompatible *************************************
539 * NAME
540 * IsCardCompatible
542 * SYNOPSIS
543 * compatible = IsCardCompatible(context)
545 * BOOL IsCardCompatible(struct BusContext *);
547 ****************************************************************************
551 BOOL IsCardCompatible(UWORD vendor_id, UWORD product_id,
552 struct DevBase *base)
554 BOOL compatible = FALSE;
555 const UWORD *p;
557 for(p = product_codes; p[0] != 0xffff; p += 2)
559 if(p[0] == vendor_id && p[1] == product_id)
560 compatible = TRUE;
563 return compatible;
568 /****i* prism2.device/GetBusType *******************************************
570 * NAME
571 * GetBusType
573 * SYNOPSIS
574 * bus_type = GetBusType(product_id)
576 * UWORD GetBusType(UWORD);
578 ****************************************************************************
582 UWORD GetBusType(UWORD product_id, struct DevBase *base)
584 UWORD bus_type;
586 switch(product_id)
588 case 0x3872:
589 case 0x3873:
590 bus_type = PCI_BUS;
591 break;
592 case 0x0131:
593 bus_type = TMD_BUS;
594 break;
595 default:
596 bus_type = PLX_BUS;
599 return bus_type;
604 /****i* prism2.device/WordsInHook ******************************************
606 * NAME
607 * WordsInHook
609 * SYNOPSIS
610 * WordsInHook(context, offset, buffer, count)
612 * VOID WordsInHook(struct BusContext *, ULONG, UWORD *, ULONG);
614 ****************************************************************************
618 static VOID WordsInHook(struct BusContext *context, ULONG offset,
619 UWORD *buffer, ULONG count)
621 volatile UWORD *reg;
623 reg = (volatile UWORD *)(context->io_base + (offset << 1));
624 while(count-- > 0)
625 *buffer++ = *reg;
627 return;
632 /****i* prism2.device/WordsOutHook *****************************************
634 * NAME
635 * WordsOutHook
637 * SYNOPSIS
638 * WordsOutHook(context, offset, buffer, count)
640 * VOID WordsOutHook(struct BusContext *, ULONG, const UWORD *, ULONG);
642 ****************************************************************************
646 static VOID WordsOutHook(struct BusContext *context, ULONG offset,
647 const UWORD *buffer, ULONG count)
649 volatile UWORD *reg;
651 reg = (volatile UWORD *)(context->io_base + (offset << 1));
652 while(count-- > 0)
653 *reg = *buffer++;
655 return;
660 /****i* prism2.device/BEWordOutHook ****************************************
662 * NAME
663 * BEWordOutHook
665 * SYNOPSIS
666 * BEWordOutHook(context, offset, value)
668 * VOID BEWordOutHook(struct BusContext *, ULONG, UWORD);
670 ****************************************************************************
674 static VOID BEWordOutHook(struct BusContext *context, ULONG offset,
675 UWORD value)
677 *(volatile UWORD *)(context->io_base + (offset << 1)) =
678 MakeBEWord(value);
680 return;
685 /****i* prism2.device/LEWordInHook *****************************************
687 * NAME
688 * LEWordInHook
690 * SYNOPSIS
691 * value = LEWordInHook(context, offset)
693 * UWORD LEWordInHook(struct BusContext *, ULONG);
695 ****************************************************************************
699 static UWORD LEWordInHook(struct BusContext *context, ULONG offset)
701 return LEWord(*(volatile UWORD *)(context->io_base + (offset << 1)));
706 /****i* prism2.device/LEWordOutHook ****************************************
708 * NAME
709 * LEWordOutHook
711 * SYNOPSIS
712 * LEWordOutHook(context, offset, value)
714 * VOID LEWordOutHook(struct BusContext *, ULONG, UWORD);
716 ****************************************************************************
720 static VOID LEWordOutHook(struct BusContext *context, ULONG offset,
721 UWORD value)
723 *(volatile UWORD *)(context->io_base + (offset << 1)) =
724 MakeLEWord(value);
726 return;
731 /****i* prism2.device/WordsInIOHook ****************************************
733 * NAME
734 * WordsInIOHook
736 * SYNOPSIS
737 * WordsInIOHook(context, offset, buffer, count)
739 * VOID WordsInIOHook(struct BusContext *, ULONG, UWORD *, ULONG);
741 ****************************************************************************
745 static VOID WordsInIOHook(struct BusContext *context, ULONG offset,
746 UWORD *buffer, ULONG count)
748 WORDSIN(context->io_base + offset, buffer, count);
750 return;
755 /****i* prism2.device/WordsOutIOHook ***************************************
757 * NAME
758 * WordsOutIOHook
760 * SYNOPSIS
761 * WordsOutIOHook(context, offset, buffer,
762 * count)
764 * VOID WordsOutIOHook(struct BusContext *, ULONG, const UWORD *,
765 * ULONG);
767 ****************************************************************************
771 static VOID WordsOutIOHook(struct BusContext *context, ULONG offset,
772 const UWORD *buffer, ULONG count)
774 WORDSOUT(context->io_base + offset, buffer, count);
776 return;
781 /****i* prism2.device/BEWordOutIOHook **************************************
783 * NAME
784 * BEWordOutIOHook
786 * SYNOPSIS
787 * BEWordOutIOHook(context, offset, value)
789 * VOID BEWordOutIOHook(struct BusContext *, ULONG, UWORD);
791 ****************************************************************************
795 static VOID BEWordOutIOHook(struct BusContext *context, ULONG offset,
796 UWORD value)
798 BEWORDOUT(context->io_base + offset, value);
800 return;
805 /****i* prism2.device/LEWordInIOHook ***************************************
807 * NAME
808 * LEWordInIOHook
810 * SYNOPSIS
811 * value = LEWordInIOHook(context, offset)
813 * UWORD LEWordInIOHook(struct BusContext *, ULONG);
815 ****************************************************************************
819 static UWORD LEWordInIOHook(struct BusContext *context, ULONG offset)
821 return LEWORDIN(context->io_base + offset);
826 /****i* prism2.device/LEWordOutIOHook **************************************
828 * NAME
829 * LEWordOutIOHook
831 * SYNOPSIS
832 * LEWordOutIOHook(context, offset, value)
834 * VOID LEWordOutIOHook(struct BusContext *, ULONG, UWORD);
836 ****************************************************************************
840 static VOID LEWordOutIOHook(struct BusContext *context, ULONG offset,
841 UWORD value)
843 LEWORDOUT(context->io_base + offset, value);
845 return;