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 "prometheus_protos.h"
38 #include "powerpci_protos.h"
39 #include "expansion_protos.h"
40 #include "openpci_protos.h"
41 #include "unit_protos.h"
44 /* Private prototypes */
46 static struct DevUnit
*FindPCIUnit(ULONG index
, struct DevBase
*base
);
47 static struct DevUnit
*CreatePCIUnit(ULONG index
, struct DevBase
*base
);
48 static struct BusContext
*AllocCard(ULONG index
, struct DevBase
*base
);
49 static VOID
FreeCard(struct BusContext
*context
, struct DevBase
*base
);
50 static BOOL
AddPCIIntServer(APTR card
, struct Interrupt
*interrupt
,
51 struct DevBase
*base
);
52 static VOID
RemPCIIntServer(APTR card
, struct Interrupt
*interrupt
,
53 struct DevBase
*base
);
54 static UBYTE
ByteInHook(struct BusContext
*context
, ULONG offset
);
55 static VOID
ByteOutHook(struct BusContext
*context
, ULONG offset
,
57 static UWORD
LEWordInHook(struct BusContext
*context
, ULONG offset
);
58 static ULONG
LELongInHook(struct BusContext
*context
, ULONG offset
);
59 static VOID
LEWordOutHook(struct BusContext
*context
, ULONG offset
,
61 static VOID
LELongOutHook(struct BusContext
*context
, ULONG offset
,
63 static APTR
AllocDMAMemHook(struct BusContext
*context
, UPINT size
,
65 static VOID
FreeDMAMemHook(struct BusContext
*context
, APTR mem
);
66 static BOOL
WrapInt(struct Interrupt
*interrupt
, struct DevBase
*base
);
67 static VOID
UnwrapInt(struct Interrupt
*interrupt
, struct DevBase
*base
);
70 const UWORD product_codes
[] =
103 static const struct TagItem unit_tags
[] =
105 {IOTAG_ByteIn
, (UPINT
)ByteInHook
},
106 {IOTAG_ByteOut
, (UPINT
)ByteOutHook
},
107 {IOTAG_LEWordIn
, (UPINT
)LEWordInHook
},
108 {IOTAG_LELongIn
, (UPINT
)LELongInHook
},
109 {IOTAG_LEWordOut
, (UPINT
)LEWordOutHook
},
110 {IOTAG_LELongOut
, (UPINT
)LELongOutHook
},
111 {IOTAG_AllocDMAMem
, (UPINT
)AllocDMAMemHook
},
112 {IOTAG_FreeDMAMem
, (UPINT
)FreeDMAMemHook
},
117 /****i* intelpro100.device/GetPCICount *************************************
120 * GetPCICount -- Get the number of compatible PCI Cards.
123 * count = GetPCICount()
125 * ULONG GetPCICount();
127 ****************************************************************************
131 ULONG
GetPCICount(struct DevBase
*base
)
135 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
136 if(base
->prometheus_base
!= NULL
)
137 count
= GetPrometheusCount(base
);
140 if(base
->powerpci_base
!= NULL
)
141 count
= GetPowerPCICount(base
);
144 if(base
->expansion_base
!= NULL
)
145 count
= GetExpansionCount(base
);
148 if(base
->openpci_base
!= NULL
)
149 count
= GetOpenPCICount(base
);
157 /****i* intelpro100.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* intelpro100.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* intelpro100.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 context
->unit_tags
= unit_tags
;
266 context
->device
= base
;
267 context
->unit
= unit
=
268 CreateUnit(index
, context
, context
->unit_tags
, PCI_BUS
, base
);
277 if(!(WrapInt(&unit
->status_int
, base
)
278 && WrapInt(&unit
->rx_int
, base
)
279 && WrapInt(&unit
->tx_int
, base
)
280 && WrapInt(&unit
->tx_end_int
, base
)))
282 success
= AddPCIIntServer(context
->card
, &unit
->status_int
, base
);
289 DeleteUnit(context
->unit
, base
);
290 FreeCard(context
, base
);
300 /****i* intelpro100.device/DeletePCIUnit ***********************************
303 * DeletePCIUnit -- Delete a unit.
306 * DeletePCIUnit(unit)
308 * VOID DeletePCIUnit(struct DevUnit *);
314 * unit - Device unit (can be NULL).
319 ****************************************************************************
323 VOID
DeletePCIUnit(struct DevUnit
*unit
, struct DevBase
*base
)
325 struct BusContext
*context
;
329 context
= unit
->card
;
330 RemPCIIntServer(context
->card
, &unit
->status_int
, base
);
331 UnwrapInt(&unit
->tx_end_int
, base
);
332 UnwrapInt(&unit
->tx_int
, base
);
333 UnwrapInt(&unit
->rx_int
, base
);
334 UnwrapInt(&unit
->status_int
, base
);
335 DeleteUnit(unit
, base
);
336 FreeCard(context
, base
);
344 /****i* intelpro100.device/AllocCard ***************************************
347 * AllocCard -- Get card from system.
350 * context = AllocCard(index)
352 * struct BusContext *AllocCard(ULONG);
354 ****************************************************************************
358 static struct BusContext
*AllocCard(ULONG index
, struct DevBase
*base
)
360 struct BusContext
*context
;
362 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
363 if(base
->prometheus_base
!= NULL
)
364 context
= AllocPrometheusCard(index
, base
);
367 if(base
->powerpci_base
!= NULL
)
368 context
= AllocPowerPCICard(index
, base
);
371 if(base
->expansion_base
!= NULL
)
372 context
= AllocExpansionCard(index
, base
);
375 if(base
->openpci_base
!= NULL
)
376 context
= AllocOpenPCICard(index
, base
);
384 /****i* intelpro100.device/FreeCard ****************************************
392 * VOID FreeCard(struct BusContext *);
394 ****************************************************************************
398 static VOID
FreeCard(struct BusContext
*context
, struct DevBase
*base
)
403 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
404 if(base
->prometheus_base
!= NULL
)
405 FreePrometheusCard(context
, base
);
408 if(base
->powerpci_base
!= NULL
)
409 FreePowerPCICard(context
, base
);
412 if(base
->expansion_base
!= NULL
)
413 FreeExpansionCard(context
, base
);
416 if(base
->openpci_base
!= NULL
)
417 FreeOpenPCICard(context
, base
);
426 /****i* intelpro100.device/AddPCIIntServer *********************************
432 * context = AddPCIIntServer(index)
434 * struct BusContext *AddPCIIntServer(ULONG);
436 ****************************************************************************
440 static BOOL
AddPCIIntServer(APTR card
, struct Interrupt
*interrupt
,
441 struct DevBase
*base
)
445 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
446 if(base
->prometheus_base
!= NULL
)
447 success
= AddPrometheusIntServer(card
, interrupt
, base
);
450 if(base
->powerpci_base
!= NULL
)
451 success
= AddPowerPCIIntServer(card
, interrupt
, base
);
454 if(base
->expansion_base
!= NULL
)
455 success
= AddExpansionIntServer(card
, interrupt
, base
);
458 if(base
->openpci_base
!= NULL
)
459 success
= AddOpenPCIIntServer(card
, interrupt
, base
);
467 /****i* intelpro100.device/RemPCIIntServer *********************************
475 * VOID RemPCIIntServer(ULONG);
477 ****************************************************************************
481 static VOID
RemPCIIntServer(APTR card
, struct Interrupt
*interrupt
,
482 struct DevBase
*base
)
484 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
485 if(base
->prometheus_base
!= NULL
)
486 RemPrometheusIntServer(card
, interrupt
, base
);
489 if(base
->powerpci_base
!= NULL
)
490 RemPowerPCIIntServer(card
, interrupt
, base
);
493 if(base
->expansion_base
!= NULL
)
494 RemExpansionIntServer(card
, interrupt
, base
);
497 if(base
->openpci_base
!= NULL
)
498 RemOpenPCIIntServer(card
, interrupt
, base
);
506 /****i* intelpro100.device/IsCardCompatible ********************************
512 * compatible = IsCardCompatible(context)
514 * BOOL IsCardCompatible(struct BusContext *);
516 ****************************************************************************
520 BOOL
IsCardCompatible(UWORD vendor_id
, UWORD product_id
,
521 struct DevBase
*base
)
523 BOOL compatible
= FALSE
;
526 for(p
= product_codes
; p
[0] != 0xffff; p
+= 2)
528 if(p
[0] == vendor_id
&& p
[1] == product_id
)
537 /****i* intelpro100.device/ByteInHook **************************************
543 * value = ByteInHook(context, offset)
545 * UBYTE ByteInHook(struct BusContext *, ULONG);
547 ****************************************************************************
551 static UBYTE
ByteInHook(struct BusContext
*context
, ULONG offset
)
553 return BYTEIN(context
->io_base
+ offset
);
558 /****i* intelpro100.device/ByteOutHook *************************************
564 * ByteOutHook(context, offset, value)
566 * VOID ByteOutHook(struct BusContext *, ULONG, UBYTE);
568 ****************************************************************************
572 static VOID
ByteOutHook(struct BusContext
*context
, ULONG offset
,
575 BYTEOUT(context
->io_base
+ offset
, value
);
582 /****i* intelpro100.device/LEWordInHook ************************************
588 * value = LEWordInHook(context, offset)
590 * UWORD LEWordInHook(struct BusContext *, ULONG);
592 ****************************************************************************
596 static UWORD
LEWordInHook(struct BusContext
*context
, ULONG offset
)
598 return LEWORDIN(context
->io_base
+ offset
);
603 /****i* intelpro100.device/LELongInHook ************************************
609 * value = LELongInHook(context, offset)
611 * ULONG LELongInHook(struct BusContext *, ULONG);
613 ****************************************************************************
617 static ULONG
LELongInHook(struct BusContext
*context
, ULONG offset
)
619 return LELONGIN(context
->io_base
+ offset
);
624 /****i* intelpro100.device/LEWordOutHook ***********************************
630 * LEWordOutHook(context, offset, value)
632 * VOID LEWordOutHook(struct BusContext *, ULONG, UWORD);
634 ****************************************************************************
638 static VOID
LEWordOutHook(struct BusContext
*context
, ULONG offset
,
641 LEWORDOUT(context
->io_base
+ offset
, value
);
648 /****i* intelpro100.device/LELongOutHook ***********************************
654 * LELongOutHook(context, offset, value)
656 * VOID LELongOutHook(struct BusContext *, ULONG, ULONG);
658 ****************************************************************************
662 static VOID
LELongOutHook(struct BusContext
*context
, ULONG offset
,
665 LELONGOUT(context
->io_base
+ offset
, value
);
672 /****i* intelpro100.device/AllocDMAMemHook *********************************
678 * mem = AllocDMAMemHook(context, size, alignment)
680 * APTR AllocDMAMemHook(struct BusContext *, UPINT, UWORD);
682 ****************************************************************************
684 * Alignment currently must be minimum of 8 bytes.
688 static APTR
AllocDMAMemHook(struct BusContext
*context
, UPINT size
,
691 struct DevBase
*base
;
692 APTR mem
= NULL
, original_mem
;
694 base
= context
->device
;
695 size
+= 2 * sizeof(APTR
) + alignment
;
696 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
697 if(base
->prometheus_base
!= NULL
)
698 original_mem
= AllocPrometheusDMAMem(size
, base
);
701 original_mem
= AllocMem(size
, MEMF_PUBLIC
);
702 if(original_mem
!= NULL
)
704 mem
= (APTR
)((UPINT
)(original_mem
+ 2 * sizeof(APTR
) + alignment
- 1)
706 *((APTR
*)mem
- 1) = original_mem
;
707 *((UPINT
*)mem
- 2) = size
;
715 /****i* intelpro100.device/FreeDMAMemHook **********************************
721 * FreeDMAMemHook(context, mem)
723 * VOID FreeDMAMemHook(struct BusContext *, APTR);
725 ****************************************************************************
729 static VOID
FreeDMAMemHook(struct BusContext
*context
, APTR mem
)
731 struct DevBase
*base
;
733 base
= context
->device
;
736 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
737 if(base
->prometheus_base
!= NULL
)
738 FreePrometheusDMAMem(*((APTR
*)mem
- 1), *((UPINT
*)mem
- 2),
742 FreeMem(*((APTR
*)mem
- 1), *((UPINT
*)mem
- 2));
750 /****i* intelpro100.device/WrapInt *****************************************
755 ****************************************************************************
759 BOOL
WrapInt(struct Interrupt
*interrupt
, struct DevBase
*base
)
762 #if defined(__amigaos4__) || defined(__MORPHOS__)
765 int_data
= AllocMem(2 * sizeof(APTR
), MEMF_PUBLIC
| MEMF_CLEAR
);
768 int_data
[0] = interrupt
->is_Code
;
769 int_data
[1] = interrupt
->is_Data
;
770 interrupt
->is_Code
= base
->wrapper_int_code
;
771 interrupt
->is_Data
= int_data
;
782 /****i* intelpro100.device/UnwrapInt ***************************************
787 ****************************************************************************
791 static VOID
UnwrapInt(struct Interrupt
*interrupt
, struct DevBase
*base
)
793 if(interrupt
->is_Code
== base
->wrapper_int_code
)
794 FreeMem(interrupt
->is_Data
, 2 * sizeof(APTR
));