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,
23 #include <exec/types.h>
24 #include <utility/tagitem.h>
27 #include <expansion/pci.h>
30 #include <proto/exec.h>
31 #include <proto/expansion.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
,
59 static VOID
WordOutHook(struct BusContext
*context
, ULONG offset
,
61 static VOID
LongOutHook(struct BusContext
*context
, ULONG offset
,
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
,
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
,
73 static VOID
LELongOutHook(struct BusContext
*context
, ULONG offset
,
75 static APTR
AllocDMAMemHook(struct BusContext
*context
, UPINT size
,
77 static VOID
FreeDMAMemHook(struct BusContext
*context
, APTR mem
);
80 const UWORD product_codes
[] =
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
},
130 /****i* etherlink3.device/GetPCICount **************************************
133 * GetPCICount -- Get the number of compatible PCI Cards.
136 * count = GetPCICount()
138 * ULONG GetPCICount();
140 ****************************************************************************
144 ULONG
GetPCICount(struct DevBase
*base
)
148 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
149 if(base
->prometheus_base
!= NULL
)
150 count
= GetPrometheusCount(base
);
153 if(base
->powerpci_base
!= NULL
)
154 count
= GetPowerPCICount(base
);
157 if(base
->expansion_base
!= NULL
)
158 count
= GetExpansionCount(base
);
161 if(base
->openpci_base
!= NULL
)
162 count
= GetOpenPCICount(base
);
170 /****i* etherlink3.device/GetPCIUnit ***************************************
173 * GetPCIUnit -- Get a unit by number.
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
);
192 unit
= CreatePCIUnit(index
, base
);
195 AddTail((APTR
)&base
->pci_units
, (APTR
)unit
);
204 /****i* etherlink3.device/FindPCIUnit **************************************
207 * FindPCIUnit -- Find a unit by number.
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
;
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
)
231 unit
= (APTR
)unit
->node
.mln_Succ
;
242 /****i* etherlink3.device/CreatePCIUnit ************************************
245 * CreatePCIUnit -- Create a PCI unit.
248 * unit = CreatePCIUnit(index)
250 * struct DevUnit *CreatePCIUnit(ULONG);
253 * Creates a new PCI unit.
255 ****************************************************************************
259 static struct DevUnit
*CreatePCIUnit(ULONG index
, struct DevBase
*base
)
262 struct BusContext
*context
;
263 struct DevUnit
*unit
= NULL
;
265 context
= AllocCard(index
, base
);
271 if(context
->unit_tags
== NULL
)
273 context
->unit_tags
= unit_tags
;
279 context
->device
= base
;
280 context
->unit
= unit
= CreateUnit(index
, context
, context
->unit_tags
,
281 context
->generation
, PCI_BUS
, base
);
290 if(!(WrapInt(&unit
->status_int
, base
)
291 && WrapInt(&unit
->rx_int
, base
)
292 && WrapInt(&unit
->tx_int
, base
)
293 && WrapInt(&unit
->tx_end_int
, base
)))
295 success
= AddPCIIntServer(context
->card
, &unit
->status_int
, base
);
302 DeleteUnit(context
->unit
, base
);
303 FreeCard(context
, base
);
313 /****i* etherlink3.device/DeletePCIUnit ************************************
316 * DeletePCIUnit -- Delete a unit.
319 * DeletePCIUnit(unit)
321 * VOID DeletePCIUnit(struct DevUnit *);
327 * unit - Device unit (can be NULL).
332 ****************************************************************************
336 VOID
DeletePCIUnit(struct DevUnit
*unit
, struct DevBase
*base
)
338 struct BusContext
*context
;
342 context
= unit
->card
;
343 RemPCIIntServer(context
->card
, &unit
->status_int
, base
);
344 UnwrapInt(&unit
->tx_end_int
, base
);
345 UnwrapInt(&unit
->tx_int
, base
);
346 UnwrapInt(&unit
->rx_int
, base
);
347 UnwrapInt(&unit
->status_int
, base
);
348 DeleteUnit(unit
, base
);
349 FreeCard(context
, base
);
357 /****i* etherlink3.device/AllocCard ****************************************
360 * AllocCard -- Get card from system.
363 * context = AllocCard(index)
365 * struct BusContext *AllocCard(ULONG);
367 ****************************************************************************
371 static struct BusContext
*AllocCard(ULONG index
, struct DevBase
*base
)
373 struct BusContext
*context
;
375 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
376 if(base
->prometheus_base
!= NULL
)
377 context
= AllocPrometheusCard(index
, base
);
380 if(base
->powerpci_base
!= NULL
)
381 context
= AllocPowerPCICard(index
, base
);
384 if(base
->expansion_base
!= NULL
)
385 context
= AllocExpansionCard(index
, base
);
388 if(base
->openpci_base
!= NULL
)
389 context
= AllocOpenPCICard(index
, base
);
397 /****i* etherlink3.device/FreeCard *****************************************
405 * VOID FreeCard(struct BusContext *);
407 ****************************************************************************
411 static VOID
FreeCard(struct BusContext
*context
, struct DevBase
*base
)
416 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
417 if(base
->prometheus_base
!= NULL
)
418 FreePrometheusCard(context
, base
);
421 if(base
->powerpci_base
!= NULL
)
422 FreePowerPCICard(context
, base
);
425 if(base
->expansion_base
!= NULL
)
426 FreeExpansionCard(context
, base
);
429 if(base
->openpci_base
!= NULL
)
430 FreeOpenPCICard(context
, base
);
439 /****i* etherlink3.device/AddPCIIntServer **********************************
445 * context = AddPCIIntServer(index)
447 * struct BusContext *AddPCIIntServer(ULONG);
449 ****************************************************************************
453 static BOOL
AddPCIIntServer(APTR card
, struct Interrupt
*interrupt
,
454 struct DevBase
*base
)
458 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
459 if(base
->prometheus_base
!= NULL
)
460 success
= AddPrometheusIntServer(card
, interrupt
, base
);
463 if(base
->powerpci_base
!= NULL
)
464 success
= AddPowerPCIIntServer(card
, interrupt
, base
);
467 if(base
->expansion_base
!= NULL
)
468 success
= AddExpansionIntServer(card
, interrupt
, base
);
471 if(base
->openpci_base
!= NULL
)
472 success
= AddOpenPCIIntServer(card
, interrupt
, base
);
480 /****i* etherlink3.device/RemPCIIntServer **********************************
488 * VOID RemPCIIntServer(ULONG);
490 ****************************************************************************
494 static VOID
RemPCIIntServer(APTR card
, struct Interrupt
*interrupt
,
495 struct DevBase
*base
)
497 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
498 if(base
->prometheus_base
!= NULL
)
499 RemPrometheusIntServer(card
, interrupt
, base
);
502 if(base
->powerpci_base
!= NULL
)
503 RemPowerPCIIntServer(card
, interrupt
, base
);
506 if(base
->expansion_base
!= NULL
)
507 RemExpansionIntServer(card
, interrupt
, base
);
510 if(base
->openpci_base
!= NULL
)
511 RemOpenPCIIntServer(card
, interrupt
, base
);
519 /****i* etherlink3.device/IsCardCompatible *********************************
525 * compatible = IsCardCompatible(vendor_id, product_id)
527 * BOOL IsCardCompatible(UWORD, UWORD);
529 ****************************************************************************
533 BOOL
IsCardCompatible(UWORD vendor_id
, UWORD product_id
,
534 struct DevBase
*base
)
536 BOOL compatible
= FALSE
;
539 for(p
= product_codes
; p
[0] != 0xffff; p
+= 2)
541 if(p
[0] == vendor_id
&& p
[1] == product_id
)
550 /****i* etherlink3.device/GetGeneration ************************************
556 * generation = GetGeneration(product_id)
558 * UWORD GetGeneration(UWORD);
560 ****************************************************************************
564 UWORD
GetGeneration(UWORD product_id
, struct DevBase
*base
)
574 generation
= VORTEX_GEN
;
579 generation
= BOOMERANG_GEN
;
591 generation
= CYCLONE_GEN
;
594 generation
= TORNADO_GEN
;
602 /****i* etherlink3.device/ByteInHook ***************************************
608 * value = ByteInHook(context, offset)
610 * UBYTE ByteInHook(struct BusContext *, ULONG);
612 ****************************************************************************
616 static UBYTE
ByteInHook(struct BusContext
*context
, ULONG offset
)
618 return BYTEIN(context
->io_base
+ offset
);
623 /****i* etherlink3.device/LongInHook ***************************************
629 * value = LongInHook(context, offset)
631 * ULONG LongInHook(struct BusContext *, ULONG);
633 ****************************************************************************
637 static ULONG
LongInHook(struct BusContext
*context
, ULONG offset
)
639 return LONGIN(context
->io_base
+ offset
);
644 /****i* etherlink3.device/ByteOutHook **************************************
650 * ByteOutHook(context, offset, value)
652 * VOID ByteOutHook(struct BusContext *, ULONG, UBYTE);
654 ****************************************************************************
658 static VOID
ByteOutHook(struct BusContext
*context
, ULONG offset
,
661 BYTEOUT(context
->io_base
+ offset
, value
);
668 /****i* etherlink3.device/WordOutHook **************************************
674 * WordOutHook(context, offset, value)
676 * VOID WordOutHook(struct BusContext *, ULONG, UWORD);
678 ****************************************************************************
682 static VOID
WordOutHook(struct BusContext
*context
, ULONG offset
,
685 WORDOUT(context
->io_base
+ offset
, value
);
692 /****i* etherlink3.device/LongOutHook **************************************
698 * LongOutHook(context, offset, value)
700 * VOID LongOutHook(struct BusContext *, ULONG, ULONG);
702 ****************************************************************************
706 static VOID
LongOutHook(struct BusContext
*context
, ULONG offset
,
709 LONGOUT(context
->io_base
+ offset
, value
);
716 /****i* etherlink3.device/LongsInHook **************************************
722 * LongsInHook(context, offset, buffer, count)
724 * VOID LongsInHook(struct BusContext *, ULONG, ULONG *, ULONG);
726 ****************************************************************************
730 static VOID
LongsInHook(struct BusContext
*context
, ULONG offset
,
731 ULONG
*buffer
, ULONG count
)
733 LONGSIN(context
->io_base
+ offset
, buffer
, count
);
740 /****i* etherlink3.device/LongsOutHook *************************************
746 * LongsOutHook(context, offset, buffer, count)
748 * VOID LongsOutHook(struct BusContext *, ULONG, const ULONG *, ULONG);
750 ****************************************************************************
754 static VOID
LongsOutHook(struct BusContext
*context
, ULONG offset
,
755 const ULONG
*buffer
, ULONG count
)
757 LONGSOUT(context
->io_base
+ offset
, buffer
, count
);
764 /****i* etherlink3.device/BEWordOutHook ************************************
770 * BEWordOutHook(context, offset, value)
772 * VOID BEWordOutHook(struct BusContext *, ULONG, UWORD);
774 ****************************************************************************
778 static VOID
BEWordOutHook(struct BusContext
*context
, ULONG offset
,
781 BEWORDOUT(context
->io_base
+ offset
, value
);
788 /****i* etherlink3.device/LEWordInHook *************************************
794 * value = LEWordInHook(context, offset)
796 * UWORD LEWordInHook(struct BusContext *, ULONG);
798 ****************************************************************************
802 static UWORD
LEWordInHook(struct BusContext
*context
, ULONG offset
)
804 return LEWORDIN(context
->io_base
+ offset
);
809 /****i* etherlink3.device/LELongInHook *************************************
815 * value = LELongInHook(context, offset)
817 * ULONG LELongInHook(struct BusContext *, ULONG);
819 ****************************************************************************
823 static ULONG
LELongInHook(struct BusContext
*context
, ULONG offset
)
825 return LELONGIN(context
->io_base
+ offset
);
830 /****i* etherlink3.device/LEWordOutHook ************************************
836 * LEWordOutHook(context, offset, value)
838 * VOID LEWordOutHook(struct BusContext *, ULONG, UWORD);
840 ****************************************************************************
844 static VOID
LEWordOutHook(struct BusContext
*context
, ULONG offset
,
847 LEWORDOUT(context
->io_base
+ offset
, value
);
854 /****i* etherlink3.device/LELongOutHook ************************************
860 * LELongOutHook(context, offset, value)
862 * VOID LELongOutHook(struct BusContext *, ULONG, ULONG);
864 ****************************************************************************
868 static VOID
LELongOutHook(struct BusContext
*context
, ULONG offset
,
871 LELONGOUT(context
->io_base
+ offset
, value
);
878 /****i* etherlink3.device/AllocDMAMemHook **********************************
884 * mem = AllocDMAMemHook(context, size, alignment)
886 * APTR AllocDMAMemHook(struct BusContext *, UPINT, UWORD);
888 ****************************************************************************
890 * Alignment currently must be minimum of 8 bytes.
894 static APTR
AllocDMAMemHook(struct BusContext
*context
, UPINT size
,
897 struct DevBase
*base
;
898 APTR mem
= NULL
, original_mem
;
900 base
= context
->device
;
901 size
+= 2 * sizeof(APTR
) + alignment
;
902 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
903 if(base
->prometheus_base
!= NULL
)
904 original_mem
= AllocPrometheusDMAMem(size
, base
);
907 original_mem
= AllocMem(size
, MEMF_PUBLIC
);
908 if(original_mem
!= NULL
)
910 mem
= (APTR
)((UPINT
)(original_mem
+ 2 * sizeof(APTR
) + alignment
- 1)
912 *((APTR
*)mem
- 1) = original_mem
;
913 *((UPINT
*)mem
- 2) = size
;
921 /****i* etherlink3.device/FreeDMAMemHook ***********************************
927 * FreeDMAMemHook(context, mem)
929 * VOID FreeDMAMemHook(struct BusContext *, APTR);
931 ****************************************************************************
935 static VOID
FreeDMAMemHook(struct BusContext
*context
, APTR mem
)
937 struct DevBase
*base
;
939 base
= context
->device
;
942 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
943 if(base
->prometheus_base
!= NULL
)
944 FreePrometheusDMAMem(*((APTR
*)mem
- 1), *((UPINT
*)mem
- 2),
948 FreeMem(*((APTR
*)mem
- 1), *((UPINT
*)mem
- 2));