3 Copyright (C) 2004-2009 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
[] =
124 static struct TagItem unit_tags
[] =
126 {IOTAG_ByteIn
, (UPINT
)ByteInHook
},
127 {IOTAG_ByteOut
, (UPINT
)ByteOutHook
},
128 {IOTAG_LEWordIn
, (UPINT
)LEWordInHook
},
129 {IOTAG_LELongIn
, (UPINT
)LELongInHook
},
130 {IOTAG_LEWordOut
, (UPINT
)LEWordOutHook
},
131 {IOTAG_LELongOut
, (UPINT
)LELongOutHook
},
132 {IOTAG_AllocDMAMem
, (UPINT
)AllocDMAMemHook
},
133 {IOTAG_FreeDMAMem
, (UPINT
)FreeDMAMemHook
},
138 /****i* intelpro100.device/GetPCICount *************************************
141 * GetPCICount -- Get the number of compatible PCI Cards.
144 * count = GetPCICount()
146 * ULONG GetPCICount();
148 ****************************************************************************
152 ULONG
GetPCICount(struct DevBase
*base
)
156 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
157 if(base
->prometheus_base
!= NULL
)
158 count
= GetPrometheusCount(base
);
160 #if defined(__mc68000__) && !defined(__AROS__)
161 if(base
->powerpci_base
!= NULL
)
162 count
= GetPowerPCICount(base
);
165 if(base
->expansion_base
!= NULL
)
166 count
= GetExpansionCount(base
);
169 if(base
->openpci_base
!= NULL
)
170 count
= GetOpenPCICount(base
);
178 /****i* intelpro100.device/GetPCIUnit **************************************
181 * GetPCIUnit -- Get a unit by number.
184 * unit = GetPCIUnit(index)
186 * struct DevUnit *GetPCIUnit(ULONG);
188 ****************************************************************************
192 struct DevUnit
*GetPCIUnit(ULONG index
, struct DevBase
*base
)
194 struct DevUnit
*unit
;
196 unit
= FindPCIUnit(index
, base
);
200 unit
= CreatePCIUnit(index
, base
);
203 AddTail((APTR
)&base
->pci_units
, (APTR
)unit
);
212 /****i* intelpro100.device/FindPCIUnit *************************************
215 * FindPCIUnit -- Find a unit by number.
218 * unit = FindPCIUnit(index)
220 * struct DevUnit *FindPCIUnit(ULONG);
222 ****************************************************************************
226 static struct DevUnit
*FindPCIUnit(ULONG index
, struct DevBase
*base
)
228 struct DevUnit
*unit
, *tail
;
231 unit
= (APTR
)base
->pci_units
.mlh_Head
;
232 tail
= (APTR
)&base
->pci_units
.mlh_Tail
;
234 while(unit
!= tail
&& !found
)
236 if(unit
->index
== index
)
239 unit
= (APTR
)unit
->node
.mln_Succ
;
250 /****i* intelpro100.device/CreatePCIUnit ***********************************
253 * CreatePCIUnit -- Create a unit.
256 * unit = CreatePCIUnit(index)
258 * struct DevUnit *CreatePCIUnit(ULONG);
261 * Creates a PCI new unit.
263 ****************************************************************************
267 static struct DevUnit
*CreatePCIUnit(ULONG index
, struct DevBase
*base
)
270 struct BusContext
*context
;
271 struct DevUnit
*unit
= NULL
;
273 context
= AllocCard(index
, base
);
279 if(context
->unit_tags
== NULL
)
281 context
->unit_tags
= unit_tags
;
287 context
->device
= base
;
288 context
->unit
= unit
=
289 CreateUnit(index
, context
, context
->unit_tags
, PCI_BUS
, base
);
298 if(!(WrapInt(&unit
->status_int
, base
)
299 && WrapInt(&unit
->rx_int
, base
)
300 && WrapInt(&unit
->tx_int
, base
)
301 && WrapInt(&unit
->tx_end_int
, base
)))
303 success
= AddPCIIntServer(context
->card
, &unit
->status_int
, base
);
310 DeleteUnit(context
->unit
, base
);
311 FreeCard(context
, base
);
321 /****i* intelpro100.device/DeletePCIUnit ***********************************
324 * DeletePCIUnit -- Delete a unit.
327 * DeletePCIUnit(unit)
329 * VOID DeletePCIUnit(struct DevUnit *);
335 * unit - Device unit (can be NULL).
340 ****************************************************************************
344 VOID
DeletePCIUnit(struct DevUnit
*unit
, struct DevBase
*base
)
346 struct BusContext
*context
;
350 context
= unit
->card
;
351 RemPCIIntServer(context
->card
, &unit
->status_int
, base
);
352 UnwrapInt(&unit
->tx_end_int
, base
);
353 UnwrapInt(&unit
->tx_int
, base
);
354 UnwrapInt(&unit
->rx_int
, base
);
355 UnwrapInt(&unit
->status_int
, base
);
356 DeleteUnit(unit
, base
);
357 FreeCard(context
, base
);
365 /****i* intelpro100.device/AllocCard ***************************************
368 * AllocCard -- Get card from system.
371 * context = AllocCard(index)
373 * struct BusContext *AllocCard(ULONG);
375 ****************************************************************************
379 static struct BusContext
*AllocCard(ULONG index
, struct DevBase
*base
)
381 struct BusContext
*context
;
383 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
384 if(base
->prometheus_base
!= NULL
)
385 context
= AllocPrometheusCard(index
, base
);
387 #if defined(__mc68000__) && !defined(__AROS__)
388 if(base
->powerpci_base
!= NULL
)
389 context
= AllocPowerPCICard(index
, base
);
392 if(base
->expansion_base
!= NULL
)
393 context
= AllocExpansionCard(index
, base
);
396 if(base
->openpci_base
!= NULL
)
397 context
= AllocOpenPCICard(index
, base
);
405 /****i* intelpro100.device/FreeCard ****************************************
413 * VOID FreeCard(struct BusContext *);
415 ****************************************************************************
419 static VOID
FreeCard(struct BusContext
*context
, struct DevBase
*base
)
424 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
425 if(base
->prometheus_base
!= NULL
)
426 FreePrometheusCard(context
, base
);
428 #if defined(__mc68000__) && !defined(__AROS__)
429 if(base
->powerpci_base
!= NULL
)
430 FreePowerPCICard(context
, base
);
433 if(base
->expansion_base
!= NULL
)
434 FreeExpansionCard(context
, base
);
437 if(base
->openpci_base
!= NULL
)
438 FreeOpenPCICard(context
, base
);
447 /****i* intelpro100.device/AddPCIIntServer *********************************
453 * context = AddPCIIntServer(index)
455 * struct BusContext *AddPCIIntServer(ULONG);
457 ****************************************************************************
461 static BOOL
AddPCIIntServer(APTR card
, struct Interrupt
*interrupt
,
462 struct DevBase
*base
)
466 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
467 if(base
->prometheus_base
!= NULL
)
468 success
= AddPrometheusIntServer(card
, interrupt
, base
);
470 #if defined(__mc68000__) && !defined(__AROS__)
471 if(base
->powerpci_base
!= NULL
)
472 success
= AddPowerPCIIntServer(card
, interrupt
, base
);
475 if(base
->expansion_base
!= NULL
)
476 success
= AddExpansionIntServer(card
, interrupt
, base
);
479 if(base
->openpci_base
!= NULL
)
480 success
= AddOpenPCIIntServer(card
, interrupt
, base
);
488 /****i* intelpro100.device/RemPCIIntServer *********************************
496 * VOID RemPCIIntServer(ULONG);
498 ****************************************************************************
502 static VOID
RemPCIIntServer(APTR card
, struct Interrupt
*interrupt
,
503 struct DevBase
*base
)
505 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
506 if(base
->prometheus_base
!= NULL
)
507 RemPrometheusIntServer(card
, interrupt
, base
);
509 #if defined(__mc68000__) && !defined(__AROS__)
510 if(base
->powerpci_base
!= NULL
)
511 RemPowerPCIIntServer(card
, interrupt
, base
);
514 if(base
->expansion_base
!= NULL
)
515 RemExpansionIntServer(card
, interrupt
, base
);
518 if(base
->openpci_base
!= NULL
)
519 RemOpenPCIIntServer(card
, interrupt
, base
);
527 /****i* intelpro100.device/IsCardCompatible ********************************
533 * compatible = IsCardCompatible(context)
535 * BOOL IsCardCompatible(struct BusContext *);
537 ****************************************************************************
541 BOOL
IsCardCompatible(UWORD vendor_id
, UWORD product_id
,
542 struct DevBase
*base
)
544 BOOL compatible
= FALSE
;
547 for(p
= product_codes
; p
[0] != 0xffff; p
+= 2)
549 if(p
[0] == vendor_id
&& p
[1] == product_id
)
558 /****i* intelpro100.device/ByteInHook **************************************
564 * value = ByteInHook(context, offset)
566 * UBYTE ByteInHook(struct BusContext *, ULONG);
568 ****************************************************************************
572 static UBYTE
ByteInHook(struct BusContext
*context
, ULONG offset
)
574 return BYTEIN(context
->io_base
+ offset
);
579 /****i* intelpro100.device/ByteOutHook *************************************
585 * ByteOutHook(context, offset, value)
587 * VOID ByteOutHook(struct BusContext *, ULONG, UBYTE);
589 ****************************************************************************
593 static VOID
ByteOutHook(struct BusContext
*context
, ULONG offset
,
596 BYTEOUT(context
->io_base
+ offset
, value
);
603 /****i* intelpro100.device/LEWordInHook ************************************
609 * value = LEWordInHook(context, offset)
611 * UWORD LEWordInHook(struct BusContext *, ULONG);
613 ****************************************************************************
617 static UWORD
LEWordInHook(struct BusContext
*context
, ULONG offset
)
619 return LEWORDIN(context
->io_base
+ offset
);
624 /****i* intelpro100.device/LELongInHook ************************************
630 * value = LELongInHook(context, offset)
632 * ULONG LELongInHook(struct BusContext *, ULONG);
634 ****************************************************************************
638 static ULONG
LELongInHook(struct BusContext
*context
, ULONG offset
)
640 return LELONGIN(context
->io_base
+ offset
);
645 /****i* intelpro100.device/LEWordOutHook ***********************************
651 * LEWordOutHook(context, offset, value)
653 * VOID LEWordOutHook(struct BusContext *, ULONG, UWORD);
655 ****************************************************************************
659 static VOID
LEWordOutHook(struct BusContext
*context
, ULONG offset
,
662 LEWORDOUT(context
->io_base
+ offset
, value
);
669 /****i* intelpro100.device/LELongOutHook ***********************************
675 * LELongOutHook(context, offset, value)
677 * VOID LELongOutHook(struct BusContext *, ULONG, ULONG);
679 ****************************************************************************
683 static VOID
LELongOutHook(struct BusContext
*context
, ULONG offset
,
686 LELONGOUT(context
->io_base
+ offset
, value
);
693 /****i* intelpro100.device/AllocDMAMemHook *********************************
699 * mem = AllocDMAMemHook(context, size, alignment)
701 * APTR AllocDMAMemHook(struct BusContext *, UPINT, UWORD);
703 ****************************************************************************
705 * Alignment currently must be minimum of 8 bytes.
709 static APTR
AllocDMAMemHook(struct BusContext
*context
, UPINT size
,
712 struct DevBase
*base
;
713 APTR mem
= NULL
, original_mem
;
715 base
= context
->device
;
716 size
+= 2 * sizeof(APTR
) + alignment
;
717 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
718 if(base
->prometheus_base
!= NULL
)
719 original_mem
= AllocPrometheusDMAMem(size
, base
);
722 original_mem
= AllocMem(size
, MEMF_PUBLIC
);
723 if(original_mem
!= NULL
)
725 mem
= (APTR
)((UPINT
)(original_mem
+ 2 * sizeof(APTR
) + alignment
- 1)
727 *((APTR
*)mem
- 1) = original_mem
;
728 *((UPINT
*)mem
- 2) = size
;
736 /****i* intelpro100.device/FreeDMAMemHook **********************************
742 * FreeDMAMemHook(context, mem)
744 * VOID FreeDMAMemHook(struct BusContext *, APTR);
746 ****************************************************************************
750 static VOID
FreeDMAMemHook(struct BusContext
*context
, APTR mem
)
752 struct DevBase
*base
;
754 base
= context
->device
;
757 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
758 if(base
->prometheus_base
!= NULL
)
759 FreePrometheusDMAMem(*((APTR
*)mem
- 1), *((UPINT
*)mem
- 2),
763 FreeMem(*((APTR
*)mem
- 1), *((UPINT
*)mem
- 2));
771 /****i* intelpro100.device/WrapInt *****************************************
776 ****************************************************************************
780 BOOL
WrapInt(struct Interrupt
*interrupt
, struct DevBase
*base
)
783 #if defined(__amigaos4__) || defined(__MORPHOS__)
786 int_data
= AllocMem(2 * sizeof(APTR
), MEMF_PUBLIC
| MEMF_CLEAR
);
789 int_data
[0] = interrupt
->is_Code
;
790 int_data
[1] = interrupt
->is_Data
;
791 interrupt
->is_Code
= base
->wrapper_int_code
;
792 interrupt
->is_Data
= int_data
;
803 /****i* intelpro100.device/UnwrapInt ***************************************
808 ****************************************************************************
812 static VOID
UnwrapInt(struct Interrupt
*interrupt
, struct DevBase
*base
)
814 if(interrupt
->is_Code
== base
->wrapper_int_code
)
815 FreeMem(interrupt
->is_Data
, 2 * sizeof(APTR
));