revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / networks / atheros5000 / pci.c
blobdceab9e2e4e5804713a0997f0adc003ab0c948ea
1 /*
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,
18 MA 02111-1307, USA.
23 #include <exec/types.h>
24 #include <utility/tagitem.h>
26 #include <proto/exec.h>
27 #include <proto/expansion.h>
29 #include "device.h"
30 #include "pci.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,
53 UWORD alignment);
54 static VOID FreeDMAMemHook(struct BusContext *context, APTR mem);
57 const UWORD product_codes[] =
59 0x10b7, 0x0013,
60 0x168c, 0x0007,
61 0x168c, 0x0012,
62 0x168c, 0x0013,
63 0x168c, 0x0015,
64 0x168c, 0x0016,
65 0x168c, 0x0017,
66 0x168c, 0x0018,
67 0x168c, 0x0019,
68 0x168c, 0x001a,
69 0x168c, 0x001b,
70 0x168c, 0x001c,
71 0x168c, 0x001d,
72 0x168c, 0x1014,
73 0x168c, 0x101a,
74 0x168c, 0x9013,
75 0xa727, 0x0013,
76 0xffff, 0xffff
80 static const struct TagItem unit_tags[] =
82 {IOTAG_AllocDMAMem, (UPINT)AllocDMAMemHook},
83 {IOTAG_FreeDMAMem, (UPINT)FreeDMAMemHook},
84 {TAG_END, 0}
88 /****i* atheros5000.device/GetPCICount *************************************
90 * NAME
91 * GetPCICount -- Get the number of compatible PCI Cards.
93 * SYNOPSIS
94 * count = GetPCICount()
96 * ULONG GetPCICount();
98 ****************************************************************************
102 ULONG GetPCICount(struct DevBase *base)
104 ULONG count = 0;
106 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
107 if(base->prometheus_base != NULL)
108 count = GetPrometheusCount(base);
109 #endif
110 #ifdef __amigaos4__
111 if(base->expansion_base != NULL)
112 count = GetExpansionCount(base);
113 #endif
114 #ifdef __MORPHOS__
115 if(base->openpci_base != NULL)
116 count = GetOpenPCICount(base);
117 #endif
119 return count;
124 /****i* atheros5000.device/GetPCIUnit **************************************
126 * NAME
127 * GetPCIUnit -- Get a unit by number.
129 * SYNOPSIS
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);
144 if(unit == NULL)
146 unit = CreatePCIUnit(index, base);
147 if(unit != NULL)
149 AddTail((APTR)&base->pci_units, (APTR)unit);
153 return unit;
158 /****i* atheros5000.device/FindPCIUnit *************************************
160 * NAME
161 * FindPCIUnit -- Find a unit by number.
163 * SYNOPSIS
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;
175 BOOL found = FALSE;
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)
183 found = TRUE;
184 else
185 unit = (APTR)unit->node.mln_Succ;
188 if(!found)
189 unit = NULL;
191 return unit;
196 /****i* atheros5000.device/CreatePCIUnit ***********************************
198 * NAME
199 * CreatePCIUnit -- Create a unit.
201 * SYNOPSIS
202 * unit = CreatePCIUnit(index)
204 * struct DevUnit *CreatePCIUnit(ULONG);
206 * FUNCTION
207 * Creates a PCI new unit.
209 ****************************************************************************
213 static struct DevUnit *CreatePCIUnit(ULONG index, struct DevBase *base)
215 BOOL success = TRUE;
216 struct BusContext *context;
217 struct DevUnit *unit = NULL;
219 context = AllocCard(index, base);
220 if(context == NULL)
221 success = FALSE;
223 if(success)
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);
232 if(unit == NULL)
233 success = FALSE;
236 /* Add interrupt */
238 if(success)
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)))
247 success = FALSE;
250 /* Add hardware interrupt and reset handler */
252 if(success)
254 if(AddPCIIntServer(context->card, &unit->status_int, base))
255 unit->flags |= UNITF_INTADDED;
256 else
257 success = FALSE;
259 #if defined(__amigaos4__) || defined(__AROS__)
260 if(AddResetCallback(&unit->reset_handler))
261 unit->flags |= UNITF_RESETADDED;
262 else
263 success = FALSE;
264 #endif
267 if(!success)
269 if(context != NULL)
271 DeleteUnit(context->unit, base);
272 FreeCard(context, base);
274 unit = NULL;
277 return unit;
282 /****i* atheros5000.device/DeletePCIUnit ***********************************
284 * NAME
285 * DeletePCIUnit -- Delete a unit.
287 * SYNOPSIS
288 * DeletePCIUnit(unit)
290 * VOID DeletePCIUnit(struct DevUnit *);
292 * FUNCTION
293 * Deletes a unit.
295 * INPUTS
296 * unit - Device unit (can be NULL).
298 * RESULT
299 * None.
301 ****************************************************************************
305 VOID DeletePCIUnit(struct DevUnit *unit, struct DevBase *base)
307 struct BusContext *context;
309 if(unit != NULL)
311 context = unit->card;
312 #if defined(__amigaos4__) || defined(__AROS__)
313 if((unit->flags & UNITF_RESETADDED) != 0)
314 RemResetCallback(&unit->reset_handler);
315 #endif
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);
329 return;
334 /****i* atheros5000.device/AllocCard ***************************************
336 * NAME
337 * AllocCard -- Get card from system.
339 * SYNOPSIS
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);
355 #endif
356 #ifdef __amigaos4__
357 if(base->expansion_base != NULL)
358 context = AllocExpansionCard(index, base);
359 #endif
360 #ifdef __MORPHOS__
361 if(base->openpci_base != NULL)
362 context = AllocOpenPCICard(index, base);
363 #endif
365 return context;
370 /****i* atheros5000.device/FreeCard ****************************************
372 * NAME
373 * FreeCard
375 * SYNOPSIS
376 * FreeCard(context)
378 * VOID FreeCard(struct BusContext *);
380 ****************************************************************************
384 static VOID FreeCard(struct BusContext *context, struct DevBase *base)
387 if(context != NULL)
389 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
390 if(base->prometheus_base != NULL)
391 FreePrometheusCard(context, base);
392 #endif
393 #ifdef __amigaos4__
394 if(base->expansion_base != NULL)
395 FreeExpansionCard(context, base);
396 #endif
397 #ifdef __MORPHOS__
398 if(base->openpci_base != NULL)
399 FreeOpenPCICard(context, base);
400 #endif
403 return;
408 /****i* atheros5000.device/AddPCIIntServer *********************************
410 * NAME
411 * AddPCIIntServer
413 * SYNOPSIS
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)
425 BOOL success;
427 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
428 if(base->prometheus_base != NULL)
429 success = AddPrometheusIntServer(card, interrupt, base);
430 #endif
431 #ifdef __amigaos4__
432 if(base->expansion_base != NULL)
433 success = AddExpansionIntServer(card, interrupt, base);
434 #endif
435 #ifdef __MORPHOS__
436 if(base->openpci_base != NULL)
437 success = AddOpenPCIIntServer(card, interrupt, base);
438 #endif
440 return success;
445 /****i* atheros5000.device/RemPCIIntServer *********************************
447 * NAME
448 * RemPCIIntServer
450 * SYNOPSIS
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);
465 #endif
466 #ifdef __amigaos4__
467 if(base->expansion_base != NULL)
468 RemExpansionIntServer(card, interrupt, base);
469 #endif
470 #ifdef __MORPHOS__
471 if(base->openpci_base != NULL)
472 RemOpenPCIIntServer(card, interrupt, base);
473 #endif
475 return;
480 /****i* atheros5000.device/IsCardCompatible ********************************
482 * NAME
483 * IsCardCompatible
485 * SYNOPSIS
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;
498 const UWORD *p;
500 for(p = product_codes; p[0] != 0xffff; p += 2)
502 if(p[0] == vendor_id && p[1] == product_id)
503 compatible = TRUE;
506 return compatible;
511 /****i* atheros5000.device/AllocDMAMemHook *********************************
513 * NAME
514 * AllocDMAMemHook
516 * SYNOPSIS
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,
528 UWORD alignment)
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);
538 else
539 #endif
540 original_mem = AllocMem(size, MEMF_PUBLIC);
541 if(original_mem != NULL)
543 mem = (APTR)((UPINT)(original_mem + 2 * sizeof(APTR) + alignment - 1)
544 & ~(alignment - 1));
545 *((APTR *)mem - 1) = original_mem;
546 *((UPINT *)mem - 2) = size;
549 return mem;
554 /****i* atheros5000.device/FreeDMAMemHook **********************************
556 * NAME
557 * FreeDMAMemHook
559 * SYNOPSIS
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;
573 if(mem != NULL)
575 #if !(defined(__MORPHOS__) || defined(__amigaos4__))
576 if(base->prometheus_base != NULL)
577 FreePrometheusDMAMem(*((APTR *)mem - 1), *((UPINT *)mem - 2),
578 base);
579 else
580 #endif
581 FreeMem(*((APTR *)mem - 1), *((UPINT *)mem - 2));
584 return;