3 Copyright (C) 2004-2013 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 "expansion_protos.h"
36 #include "openpci_protos.h"
37 #include "unit_protos.h"
40 /* Private prototypes */
42 static struct DevUnit
*FindPCIUnit(ULONG index
, struct DevBase
*base
);
43 static struct DevUnit
*CreatePCIUnit(ULONG index
, struct DevBase
*base
);
44 static struct BusContext
*AllocCard(ULONG index
, struct DevBase
*base
);
45 static VOID
FreeCard(struct BusContext
*context
, struct DevBase
*base
);
46 static BOOL
AddPCIIntServer(APTR card
, struct Interrupt
*interrupt
,
47 struct DevBase
*base
);
48 static VOID
RemPCIIntServer(APTR card
, struct Interrupt
*interrupt
,
49 struct DevBase
*base
);
50 BOOL
IsCardCompatible(UWORD vendor_id
, UWORD product_id
,
51 struct DevBase
*base
);
52 static APTR
AllocDMAMemHook(struct BusContext
*context
, UPINT size
,
54 static VOID
FreeDMAMemHook(struct BusContext
*context
, APTR mem
);
57 const UWORD product_codes
[] =
80 static const struct TagItem unit_tags
[] =
82 {IOTAG_AllocDMAMem
, (UPINT
)AllocDMAMemHook
},
83 {IOTAG_FreeDMAMem
, (UPINT
)FreeDMAMemHook
},
88 /****i* atheros5000.device/GetPCICount *************************************
91 * GetPCICount -- Get the number of compatible PCI Cards.
94 * count = GetPCICount()
96 * ULONG GetPCICount();
98 ****************************************************************************
102 ULONG
GetPCICount(struct DevBase
*base
)
106 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
107 if(base
->prometheus_base
!= NULL
)
108 count
= GetPrometheusCount(base
);
111 if(base
->expansion_base
!= NULL
)
112 count
= GetExpansionCount(base
);
115 if(base
->openpci_base
!= NULL
)
116 count
= GetOpenPCICount(base
);
124 /****i* atheros5000.device/GetPCIUnit **************************************
127 * GetPCIUnit -- Get a unit by number.
130 * unit = GetPCIUnit(index)
132 * struct DevUnit *GetPCIUnit(ULONG);
134 ****************************************************************************
138 struct DevUnit
*GetPCIUnit(ULONG index
, struct DevBase
*base
)
140 struct DevUnit
*unit
;
142 unit
= FindPCIUnit(index
, base
);
146 unit
= CreatePCIUnit(index
, base
);
149 AddTail((APTR
)&base
->pci_units
, (APTR
)unit
);
158 /****i* atheros5000.device/FindPCIUnit *************************************
161 * FindPCIUnit -- Find a unit by number.
164 * unit = FindPCIUnit(index)
166 * struct DevUnit *FindPCIUnit(ULONG);
168 ****************************************************************************
172 static struct DevUnit
*FindPCIUnit(ULONG index
, struct DevBase
*base
)
174 struct DevUnit
*unit
, *tail
;
177 unit
= (APTR
)base
->pci_units
.mlh_Head
;
178 tail
= (APTR
)&base
->pci_units
.mlh_Tail
;
180 while(unit
!= tail
&& !found
)
182 if(unit
->index
== index
)
185 unit
= (APTR
)unit
->node
.mln_Succ
;
196 /****i* atheros5000.device/CreatePCIUnit ***********************************
199 * CreatePCIUnit -- Create a unit.
202 * unit = CreatePCIUnit(index)
204 * struct DevUnit *CreatePCIUnit(ULONG);
207 * Creates a PCI new unit.
209 ****************************************************************************
213 static struct DevUnit
*CreatePCIUnit(ULONG index
, struct DevBase
*base
)
216 struct BusContext
*context
;
217 struct DevUnit
*unit
= NULL
;
219 context
= AllocCard(index
, base
);
225 if(context
->unit_tags
== NULL
)
226 context
->unit_tags
= unit_tags
;
228 context
->device
= base
;
229 context
->unit
= unit
=
230 CreateUnit(index
, (APTR
)context
->io_base
, context
->id
, context
,
231 context
->unit_tags
, 0, base
);
240 if(!(WrapInt(&unit
->status_int
, base
)
241 && WrapInt(&unit
->rx_int
, base
)
242 && WrapInt(&unit
->tx_int
, base
)
243 && WrapInt(&unit
->tx_end_int
, base
)
244 && WrapInt(&unit
->mgmt_int
, base
)
245 && WrapInt(&unit
->mgmt_end_int
, base
)
246 && WrapInt(&unit
->reset_handler
, base
)))
250 /* Add hardware interrupt and reset handler */
254 if(AddPCIIntServer(context
->card
, &unit
->status_int
, base
))
255 unit
->flags
|= UNITF_INTADDED
;
259 #if defined(__amigaos4__) || defined(__AROS__)
260 if(AddResetCallback(&unit
->reset_handler
))
261 unit
->flags
|= UNITF_RESETADDED
;
271 DeleteUnit(context
->unit
, base
);
272 FreeCard(context
, base
);
282 /****i* atheros5000.device/DeletePCIUnit ***********************************
285 * DeletePCIUnit -- Delete a unit.
288 * DeletePCIUnit(unit)
290 * VOID DeletePCIUnit(struct DevUnit *);
296 * unit - Device unit (can be NULL).
301 ****************************************************************************
305 VOID
DeletePCIUnit(struct DevUnit
*unit
, struct DevBase
*base
)
307 struct BusContext
*context
;
311 context
= unit
->card
;
312 #if defined(__amigaos4__) || defined(__AROS__)
313 if((unit
->flags
& UNITF_RESETADDED
) != 0)
314 RemResetCallback(&unit
->reset_handler
);
316 if((unit
->flags
& UNITF_INTADDED
) != 0)
317 RemPCIIntServer(context
->card
, &unit
->status_int
, base
);
318 UnwrapInt(&unit
->reset_handler
, base
);
319 UnwrapInt(&unit
->mgmt_end_int
, base
);
320 UnwrapInt(&unit
->mgmt_int
, base
);
321 UnwrapInt(&unit
->tx_end_int
, base
);
322 UnwrapInt(&unit
->tx_int
, base
);
323 UnwrapInt(&unit
->rx_int
, base
);
324 UnwrapInt(&unit
->status_int
, base
);
325 DeleteUnit(unit
, base
);
326 FreeCard(context
, base
);
334 /****i* atheros5000.device/AllocCard ***************************************
337 * AllocCard -- Get card from system.
340 * context = AllocCard(index)
342 * struct BusContext *AllocCard(ULONG);
344 ****************************************************************************
348 static struct BusContext
*AllocCard(ULONG index
, struct DevBase
*base
)
350 struct BusContext
*context
;
352 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
353 if(base
->prometheus_base
!= NULL
)
354 context
= AllocPrometheusCard(index
, base
);
357 if(base
->expansion_base
!= NULL
)
358 context
= AllocExpansionCard(index
, base
);
361 if(base
->openpci_base
!= NULL
)
362 context
= AllocOpenPCICard(index
, base
);
370 /****i* atheros5000.device/FreeCard ****************************************
378 * VOID FreeCard(struct BusContext *);
380 ****************************************************************************
384 static VOID
FreeCard(struct BusContext
*context
, struct DevBase
*base
)
389 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
390 if(base
->prometheus_base
!= NULL
)
391 FreePrometheusCard(context
, base
);
394 if(base
->expansion_base
!= NULL
)
395 FreeExpansionCard(context
, base
);
398 if(base
->openpci_base
!= NULL
)
399 FreeOpenPCICard(context
, base
);
408 /****i* atheros5000.device/AddPCIIntServer *********************************
414 * success = AddPCIIntServer(card, interrupt)
416 * BOOL AddPCIIntServer(APTR, struct Interrupt *);
418 ****************************************************************************
422 static BOOL
AddPCIIntServer(APTR card
, struct Interrupt
*interrupt
,
423 struct DevBase
*base
)
427 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
428 if(base
->prometheus_base
!= NULL
)
429 success
= AddPrometheusIntServer(card
, interrupt
, base
);
432 if(base
->expansion_base
!= NULL
)
433 success
= AddExpansionIntServer(card
, interrupt
, base
);
436 if(base
->openpci_base
!= NULL
)
437 success
= AddOpenPCIIntServer(card
, interrupt
, base
);
445 /****i* atheros5000.device/RemPCIIntServer *********************************
451 * RemPCIIntServer(card, interrupt)
453 * VOID RemPCIIntServer(APTR, struct Interrupt *);
455 ****************************************************************************
459 static VOID
RemPCIIntServer(APTR card
, struct Interrupt
*interrupt
,
460 struct DevBase
*base
)
462 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
463 if(base
->prometheus_base
!= NULL
)
464 RemPrometheusIntServer(card
, interrupt
, base
);
467 if(base
->expansion_base
!= NULL
)
468 RemExpansionIntServer(card
, interrupt
, base
);
471 if(base
->openpci_base
!= NULL
)
472 RemOpenPCIIntServer(card
, interrupt
, base
);
480 /****i* atheros5000.device/IsCardCompatible ********************************
486 * compatible = IsCardCompatible(context)
488 * BOOL IsCardCompatible(struct BusContext *);
490 ****************************************************************************
494 BOOL
IsCardCompatible(UWORD vendor_id
, UWORD product_id
,
495 struct DevBase
*base
)
497 BOOL compatible
= FALSE
;
500 for(p
= product_codes
; p
[0] != 0xffff; p
+= 2)
502 if(p
[0] == vendor_id
&& p
[1] == product_id
)
511 /****i* atheros5000.device/AllocDMAMemHook *********************************
517 * mem = AllocDMAMemHook(context, size, alignment)
519 * APTR AllocDMAMemHook(struct BusContext *, UPINT, UWORD);
521 ****************************************************************************
523 * Alignment currently must be minimum of 8 bytes.
527 static APTR
AllocDMAMemHook(struct BusContext
*context
, UPINT size
,
530 struct DevBase
*base
;
531 APTR mem
= NULL
, original_mem
;
533 base
= context
->device
;
534 size
+= 2 * sizeof(APTR
) + alignment
;
535 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
536 if(base
->prometheus_base
!= NULL
)
537 original_mem
= AllocPrometheusDMAMem(size
, base
);
540 original_mem
= AllocMem(size
, MEMF_PUBLIC
);
541 if(original_mem
!= NULL
)
543 mem
= (APTR
)((UPINT
)(original_mem
+ 2 * sizeof(APTR
) + alignment
- 1)
545 *((APTR
*)mem
- 1) = original_mem
;
546 *((UPINT
*)mem
- 2) = size
;
554 /****i* atheros5000.device/FreeDMAMemHook **********************************
560 * FreeDMAMemHook(context, mem)
562 * VOID FreeDMAMemHook(struct BusContext *, APTR);
564 ****************************************************************************
568 static VOID
FreeDMAMemHook(struct BusContext
*context
, APTR mem
)
570 struct DevBase
*base
;
572 base
= context
->device
;
575 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
576 if(base
->prometheus_base
!= NULL
)
577 FreePrometheusDMAMem(*((APTR
*)mem
- 1), *((UPINT
*)mem
- 2),
581 FreeMem(*((APTR
*)mem
- 1), *((UPINT
*)mem
- 2));