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,
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
);
152 #if defined(__mc68000__) && !defined(__AROS__)
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
)
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
);
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
)))
289 success
= AddPCIIntServer(context
->card
, &unit
->status_int
, base
);
296 DeleteUnit(context
->unit
, base
);
297 FreeCard(context
, base
);
307 /****i* etherlink3.device/DeletePCIUnit ************************************
310 * DeletePCIUnit -- Delete a unit.
313 * DeletePCIUnit(unit)
315 * VOID DeletePCIUnit(struct DevUnit *);
321 * unit - Device unit (can be NULL).
326 ****************************************************************************
330 VOID
DeletePCIUnit(struct DevUnit
*unit
, struct DevBase
*base
)
332 struct BusContext
*context
;
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
);
351 /****i* etherlink3.device/AllocCard ****************************************
354 * AllocCard -- Get card from system.
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
);
373 #if defined(__mc68000__) && !defined(__AROS__)
374 if(base
->powerpci_base
!= NULL
)
375 context
= AllocPowerPCICard(index
, base
);
378 if(base
->expansion_base
!= NULL
)
379 context
= AllocExpansionCard(index
, base
);
382 if(base
->openpci_base
!= NULL
)
383 context
= AllocOpenPCICard(index
, base
);
391 /****i* etherlink3.device/FreeCard *****************************************
399 * VOID FreeCard(struct BusContext *);
401 ****************************************************************************
405 static VOID
FreeCard(struct BusContext
*context
, struct DevBase
*base
)
410 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
411 if(base
->prometheus_base
!= NULL
)
412 FreePrometheusCard(context
, base
);
414 #if defined(__mc68000) && !defined(__AROS__)
415 if(base
->powerpci_base
!= NULL
)
416 FreePowerPCICard(context
, base
);
419 if(base
->expansion_base
!= NULL
)
420 FreeExpansionCard(context
, base
);
423 if(base
->openpci_base
!= NULL
)
424 FreeOpenPCICard(context
, base
);
433 /****i* etherlink3.device/AddPCIIntServer **********************************
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
)
452 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
453 if(base
->prometheus_base
!= NULL
)
454 success
= AddPrometheusIntServer(card
, interrupt
, base
);
456 #if defined(__mc68000) && !defined(__AROS__)
457 if(base
->powerpci_base
!= NULL
)
458 success
= AddPowerPCIIntServer(card
, interrupt
, base
);
461 if(base
->expansion_base
!= NULL
)
462 success
= AddExpansionIntServer(card
, interrupt
, base
);
465 if(base
->openpci_base
!= NULL
)
466 success
= AddOpenPCIIntServer(card
, interrupt
, base
);
474 /****i* etherlink3.device/RemPCIIntServer **********************************
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
);
495 #if defined(__mc68000) && !defined(__AROS__)
496 if(base
->powerpci_base
!= NULL
)
497 RemPowerPCIIntServer(card
, interrupt
, base
);
500 if(base
->expansion_base
!= NULL
)
501 RemExpansionIntServer(card
, interrupt
, base
);
504 if(base
->openpci_base
!= NULL
)
505 RemOpenPCIIntServer(card
, interrupt
, base
);
513 /****i* etherlink3.device/IsCardCompatible *********************************
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
;
533 for(p
= product_codes
; p
[0] != 0xffff; p
+= 2)
535 if(p
[0] == vendor_id
&& p
[1] == product_id
)
544 /****i* etherlink3.device/GetGeneration ************************************
550 * generation = GetGeneration(product_id)
552 * UWORD GetGeneration(UWORD);
554 ****************************************************************************
558 UWORD
GetGeneration(UWORD product_id
, struct DevBase
*base
)
568 generation
= VORTEX_GEN
;
573 generation
= BOOMERANG_GEN
;
585 generation
= CYCLONE_GEN
;
588 generation
= TORNADO_GEN
;
596 /****i* etherlink3.device/ByteInHook ***************************************
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 ***************************************
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 **************************************
644 * ByteOutHook(context, offset, value)
646 * VOID ByteOutHook(struct BusContext *, ULONG, UBYTE);
648 ****************************************************************************
652 static VOID
ByteOutHook(struct BusContext
*context
, ULONG offset
,
655 BYTEOUT(context
->io_base
+ offset
, value
);
662 /****i* etherlink3.device/WordOutHook **************************************
668 * WordOutHook(context, offset, value)
670 * VOID WordOutHook(struct BusContext *, ULONG, UWORD);
672 ****************************************************************************
676 static VOID
WordOutHook(struct BusContext
*context
, ULONG offset
,
679 WORDOUT(context
->io_base
+ offset
, value
);
686 /****i* etherlink3.device/LongOutHook **************************************
692 * LongOutHook(context, offset, value)
694 * VOID LongOutHook(struct BusContext *, ULONG, ULONG);
696 ****************************************************************************
700 static VOID
LongOutHook(struct BusContext
*context
, ULONG offset
,
703 LONGOUT(context
->io_base
+ offset
, value
);
710 /****i* etherlink3.device/LongsInHook **************************************
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
);
734 /****i* etherlink3.device/LongsOutHook *************************************
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
);
758 /****i* etherlink3.device/BEWordOutHook ************************************
764 * BEWordOutHook(context, offset, value)
766 * VOID BEWordOutHook(struct BusContext *, ULONG, UWORD);
768 ****************************************************************************
772 static VOID
BEWordOutHook(struct BusContext
*context
, ULONG offset
,
775 BEWORDOUT(context
->io_base
+ offset
, value
);
782 /****i* etherlink3.device/LEWordInHook *************************************
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 *************************************
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 ************************************
830 * LEWordOutHook(context, offset, value)
832 * VOID LEWordOutHook(struct BusContext *, ULONG, UWORD);
834 ****************************************************************************
838 static VOID
LEWordOutHook(struct BusContext
*context
, ULONG offset
,
841 LEWORDOUT(context
->io_base
+ offset
, value
);
848 /****i* etherlink3.device/LELongOutHook ************************************
854 * LELongOutHook(context, offset, value)
856 * VOID LELongOutHook(struct BusContext *, ULONG, ULONG);
858 ****************************************************************************
862 static VOID
LELongOutHook(struct BusContext
*context
, ULONG offset
,
865 LELONGOUT(context
->io_base
+ offset
, value
);
872 /****i* etherlink3.device/AllocDMAMemHook **********************************
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
,
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
);
901 original_mem
= AllocMem(size
, MEMF_PUBLIC
);
902 if(original_mem
!= NULL
)
904 mem
= (APTR
)((UPINT
)(original_mem
+ 2 * sizeof(APTR
) + alignment
- 1)
906 *((APTR
*)mem
- 1) = original_mem
;
907 *((UPINT
*)mem
- 2) = size
;
915 /****i* etherlink3.device/FreeDMAMemHook ***********************************
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
;
936 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
937 if(base
->prometheus_base
!= NULL
)
938 FreePrometheusDMAMem(*((APTR
*)mem
- 1), *((UPINT
*)mem
- 2),
942 FreeMem(*((APTR
*)mem
- 1), *((UPINT
*)mem
- 2));