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,
23 #include <exec/types.h>
24 #include <utility/tagitem.h>
26 #include <proto/exec.h>
27 #include <proto/expansion.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
,
60 static UWORD
LEWordInHook(struct BusContext
*context
, ULONG offset
);
61 static VOID
LEWordOutHook(struct BusContext
*context
, ULONG offset
,
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
,
69 static UWORD
LEWordInIOHook(struct BusContext
*context
, ULONG offset
);
70 static VOID
LEWordOutIOHook(struct BusContext
*context
, ULONG offset
,
74 const UWORD product_codes
[] =
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
},
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
},
115 /****i* prism2.device/GetPCICount ******************************************
118 * GetPCICount -- Get the number of compatible PCI Cards.
121 * count = GetPCICount()
123 * ULONG GetPCICount();
125 ****************************************************************************
129 ULONG
GetPCICount(struct DevBase
*base
)
133 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
134 if(base
->prometheus_base
!= NULL
)
135 count
= GetPrometheusCount(base
);
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
);
144 if(base
->expansion_base
!= NULL
)
145 count
= GetExpansionCount(base
);
148 if(base
->openpci_base
!= NULL
)
149 count
= GetOpenPCICount(base
);
157 /****i* prism2.device/GetPCIUnit *******************************************
160 * GetPCIUnit -- Get a unit by number.
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
);
179 unit
= CreatePCIUnit(index
, base
);
182 AddTail((APTR
)&base
->pci_units
, (APTR
)unit
);
191 /****i* prism2.device/FindPCIUnit ******************************************
194 * FindPCIUnit -- Find a unit by number.
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
;
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
)
218 unit
= (APTR
)unit
->node
.mln_Succ
;
229 /****i* prism2.device/CreatePCIUnit ****************************************
232 * CreatePCIUnit -- Create a unit.
235 * unit = CreatePCIUnit(index)
237 * struct DevUnit *CreatePCIUnit(ULONG);
240 * Creates a PCI new unit.
242 ****************************************************************************
246 static struct DevUnit
*CreatePCIUnit(ULONG index
, struct DevBase
*base
)
249 struct BusContext
*context
;
250 struct DevUnit
*unit
= NULL
;
252 context
= AllocCard(index
, base
);
258 if(context
->unit_tags
== NULL
)
260 if(context
->bus_type
== PCI_BUS
)
261 context
->unit_tags
= unit_tags
;
263 context
->unit_tags
= bridge_unit_tags
;
266 context
->unit
= unit
=
267 CreateUnit(index
, context
, context
->unit_tags
, context
->bus_type
,
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
)))
285 /* Add hardware interrupt and reset handler */
289 if(AddPCIIntServer(context
->card
, &unit
->status_int
, base
))
290 unit
->flags
|= UNITF_INTADDED
;
294 #if defined(__amigaos4__) || defined(__AROS__)
295 if(AddResetCallback(&unit
->reset_handler
))
296 unit
->flags
|= UNITF_RESETADDED
;
306 DeleteUnit(context
->unit
, base
);
307 FreeCard(context
, base
);
317 /****i* prism2.device/DeletePCIUnit ****************************************
320 * DeletePCIUnit -- Delete a unit.
323 * DeletePCIUnit(unit)
325 * VOID DeletePCIUnit(struct DevUnit *);
331 * unit - Device unit (can be NULL).
336 ****************************************************************************
340 VOID
DeletePCIUnit(struct DevUnit
*unit
, struct DevBase
*base
)
342 struct BusContext
*context
;
346 context
= unit
->card
;
347 #if defined(__amigaos4__) || defined(__AROS__)
348 if((unit
->flags
& UNITF_RESETADDED
) != 0)
349 RemResetCallback(&unit
->reset_handler
);
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
);
367 /****i* prism2.device/AllocCard ********************************************
370 * AllocCard -- Get card from system.
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
);
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
);
396 if(base
->expansion_base
!= NULL
)
397 context
= AllocExpansionCard(index
, base
);
400 if(base
->openpci_base
!= NULL
)
401 context
= AllocOpenPCICard(index
, base
);
409 /****i* prism2.device/FreeCard *********************************************
417 * VOID FreeCard(struct BusContext *);
419 ****************************************************************************
423 static VOID
FreeCard(struct BusContext
*context
, struct DevBase
*base
)
428 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
429 if(base
->prometheus_base
!= NULL
)
430 FreePrometheusCard(context
, base
);
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
);
439 if(base
->expansion_base
!= NULL
)
440 FreeExpansionCard(context
, base
);
443 if(base
->openpci_base
!= NULL
)
444 FreeOpenPCICard(context
, base
);
453 /****i* prism2.device/AddPCIIntServer **************************************
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
)
472 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
473 if(base
->prometheus_base
!= NULL
)
474 success
= AddPrometheusIntServer(card
, interrupt
, base
);
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
);
483 if(base
->expansion_base
!= NULL
)
484 success
= AddExpansionIntServer(card
, interrupt
, base
);
487 if(base
->openpci_base
!= NULL
)
488 success
= AddOpenPCIIntServer(card
, interrupt
, base
);
496 /****i* prism2.device/RemPCIIntServer **************************************
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
);
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
);
524 if(base
->expansion_base
!= NULL
)
525 RemExpansionIntServer(card
, interrupt
, base
);
528 if(base
->openpci_base
!= NULL
)
529 RemOpenPCIIntServer(card
, interrupt
, base
);
537 /****i* prism2.device/IsCardCompatible *************************************
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
;
557 for(p
= product_codes
; p
[0] != 0xffff; p
+= 2)
559 if(p
[0] == vendor_id
&& p
[1] == product_id
)
568 /****i* prism2.device/GetBusType *******************************************
574 * bus_type = GetBusType(product_id)
576 * UWORD GetBusType(UWORD);
578 ****************************************************************************
582 UWORD
GetBusType(UWORD product_id
, struct DevBase
*base
)
604 /****i* prism2.device/WordsInHook ******************************************
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
)
623 reg
= (volatile UWORD
*)(context
->io_base
+ (offset
<< 1));
632 /****i* prism2.device/WordsOutHook *****************************************
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
)
651 reg
= (volatile UWORD
*)(context
->io_base
+ (offset
<< 1));
660 /****i* prism2.device/BEWordOutHook ****************************************
666 * BEWordOutHook(context, offset, value)
668 * VOID BEWordOutHook(struct BusContext *, ULONG, UWORD);
670 ****************************************************************************
674 static VOID
BEWordOutHook(struct BusContext
*context
, ULONG offset
,
677 *(volatile UWORD
*)(context
->io_base
+ (offset
<< 1)) =
685 /****i* prism2.device/LEWordInHook *****************************************
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 ****************************************
712 * LEWordOutHook(context, offset, value)
714 * VOID LEWordOutHook(struct BusContext *, ULONG, UWORD);
716 ****************************************************************************
720 static VOID
LEWordOutHook(struct BusContext
*context
, ULONG offset
,
723 *(volatile UWORD
*)(context
->io_base
+ (offset
<< 1)) =
731 /****i* prism2.device/WordsInIOHook ****************************************
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
);
755 /****i* prism2.device/WordsOutIOHook ***************************************
761 * WordsOutIOHook(context, offset, buffer,
764 * VOID WordsOutIOHook(struct BusContext *, ULONG, const UWORD *,
767 ****************************************************************************
771 static VOID
WordsOutIOHook(struct BusContext
*context
, ULONG offset
,
772 const UWORD
*buffer
, ULONG count
)
774 WORDSOUT(context
->io_base
+ offset
, buffer
, count
);
781 /****i* prism2.device/BEWordOutIOHook **************************************
787 * BEWordOutIOHook(context, offset, value)
789 * VOID BEWordOutIOHook(struct BusContext *, ULONG, UWORD);
791 ****************************************************************************
795 static VOID
BEWordOutIOHook(struct BusContext
*context
, ULONG offset
,
798 BEWORDOUT(context
->io_base
+ offset
, value
);
805 /****i* prism2.device/LEWordInIOHook ***************************************
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 **************************************
832 * LEWordOutIOHook(context, offset, value)
834 * VOID LEWordOutIOHook(struct BusContext *, ULONG, UWORD);
836 ****************************************************************************
840 static VOID
LEWordOutIOHook(struct BusContext
*context
, ULONG offset
,
843 LEWORDOUT(context
->io_base
+ offset
, value
);