Fixed binary search: no more infinite loops when vendor is unknown.
[tangerine.git] / workbench / devs / networks / prism2 / prometheus.c
blobafa080e50948a3afd8b78e1f2349a8de26267a39
1 /*
3 File: prometheus.c
4 Author: Neil Cafferkey
5 Copyright (C) 2004,2005 Neil Cafferkey
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20 MA 02111-1307, USA.
25 #include <exec/types.h>
26 #include <libraries/prometheus.h>
28 #include <proto/exec.h>
29 #include <proto/prometheus.h>
31 #include "device.h"
32 #include "pci.h"
34 #include "pci_protos.h"
35 #include "prometheus_protos.h"
38 #define RETRY_COUNT 15
40 #define PLX9052_INTS 0x4c
41 #define PLX9052_CNTRL 0x50
43 #define PLX9052_CNTRLB_PCI21 14
44 #define PLX9052_CNTRLB_RETRIES 19
46 #define PLX9052_CNTRLF_PCI21 (1 << PLX9052_CNTRLB_PCI21)
47 #define PLX9052_CNTRLF_RETRIES (0xf << PLX9052_CNTRLB_RETRIES)
50 /****i* prism2.device/GetPrometheusCount ***********************************
52 * NAME
53 * GetPrometheusCount
55 * SYNOPSIS
56 * count = GetPrometheusCount()
58 * ULONG GetPrometheusCount();
60 ****************************************************************************
64 ULONG GetPrometheusCount(struct DevBase *base)
66 ULONG count = 0;
67 PCIBoard *card = NULL;
68 UPINT vendor_id, product_id;
70 while((card = Prm_FindBoardTagList(card, NULL)) != NULL)
72 Prm_GetBoardAttrsTags(card, PRM_Vendor, (UPINT)&vendor_id,
73 PRM_Device, (UPINT)&product_id, TAG_END);
74 if(IsCardCompatible(vendor_id, product_id, base))
75 count++;
78 return count;
83 /****i* prism2.device/AllocPrometheusCard **********************************
85 * NAME
86 * AllocPrometheusCard -- Create a unit.
88 * SYNOPSIS
89 * context = AllocPrometheusCard(index)
91 * struct BusContext *AllocPrometheusCard(ULONG);
93 ****************************************************************************
97 struct BusContext *AllocPrometheusCard(ULONG index, struct DevBase *base)
99 BOOL success = TRUE;
100 struct BusContext *context;
101 PCIBoard *card = NULL;
102 UWORD i = 0;
103 UPINT vendor_id, product_id, plx_base;
104 UBYTE io_range_no;
105 volatile UBYTE *cor_reg;
106 ULONG pci_control;
108 /* Find a compatible card */
110 context = AllocMem(sizeof(struct BusContext), MEMF_PUBLIC | MEMF_CLEAR);
111 if(context == NULL)
112 success = FALSE;
114 if(success)
116 while(i <= index)
118 card = Prm_FindBoardTagList(card, NULL);
119 Prm_GetBoardAttrsTags(card, PRM_Vendor, (UPINT)&vendor_id,
120 PRM_Device, (UPINT)&product_id, TAG_END);
121 if(IsCardCompatible(vendor_id, product_id, base))
122 i++;
125 context->card = card;
126 if(card == NULL)
127 success = FALSE;
130 if(success)
132 /* Find out what type of Prism II PCI card this is */
134 context->bus_type = GetBusType(product_id, base);
136 if(context->bus_type == TMD_BUS)
138 /* Enable the PCCard */
140 Prm_GetBoardAttrsTags(card, PRM_MemoryAddr1, (UPINT)&cor_reg,
141 TAG_END);
142 BYTEOUT((UPINT)cor_reg, COR_VALUE);
143 io_range_no = 2;
145 else if(context->bus_type == PLX_BUS)
147 /* Enable interrupts on the bridge */
149 Prm_GetBoardAttrsTags(card, PRM_MemoryAddr1, (UPINT)&plx_base,
150 TAG_END);
151 LELONGOUT(plx_base + PLX9052_INTS,
152 LELONGIN(plx_base + PLX9052_INTS) | (1 << 6));
154 #ifdef __mc68000
155 /* Delay PCI retries as long as possible, so that they will
156 hopefully never occur */
158 pci_control = LELONGIN(plx_base + PLX9052_CNTRL);
159 pci_control &= ~(PLX9052_CNTRLF_RETRIES | PLX9052_CNTRLF_PCI21);
160 pci_control |= RETRY_COUNT << PLX9052_CNTRLB_RETRIES;
161 LELONGOUT(plx_base + PLX9052_CNTRL, pci_control);
162 #endif
164 /* Enable the PCCard */
166 Prm_GetBoardAttrsTags(card, PRM_MemoryAddr2, (UPINT)&cor_reg,
167 TAG_END);
168 cor_reg += 0x3e0;
169 *cor_reg = COR_VALUE;
170 io_range_no = 3;
172 else
173 io_range_no = 0;
175 /* Get the I/O base of the wireless chip */
177 Prm_GetBoardAttrsTags(card, PRM_MemoryAddr0 + io_range_no,
178 (UPINT)&context->io_base, TAG_END);
179 if(context->io_base == 0)
180 success = FALSE;
183 /* Lock card */
185 if(success)
187 if(!Prm_SetBoardAttrsTags(card, PRM_BoardOwner, (UPINT)base, TAG_END))
188 success = FALSE;
191 if(!success)
193 FreePrometheusCard(context, base);
194 context = NULL;
197 return context;
202 /****i* prism2.device/FreePrometheusCard ***********************************
204 * NAME
205 * FreePrometheusCard
207 * SYNOPSIS
208 * FreePrometheusCard(context)
210 * VOID FreePrometheusCard(struct BusContext *);
212 ****************************************************************************
216 VOID FreePrometheusCard(struct BusContext *context, struct DevBase *base)
218 PCIBoard *card;
219 APTR owner;
221 if(context != NULL)
223 card = context->card;
224 if(card != NULL)
226 /* Unlock board */
228 Prm_GetBoardAttrsTags(card, PRM_BoardOwner, (UPINT)&owner,
229 TAG_END);
230 if(owner == base)
231 Prm_SetBoardAttrsTags(card, PRM_BoardOwner, NULL, TAG_END);
234 FreeMem(context, sizeof(struct BusContext));
237 return;
242 /****i* prism2.device/AddPrometheusIntServer *******************************
244 * NAME
245 * AddPrometheusIntServer
247 * SYNOPSIS
248 * context = AddPrometheusIntServer(index)
250 * struct BusContext *AddPrometheusIntServer(ULONG);
252 ****************************************************************************
256 BOOL AddPrometheusIntServer(APTR card, struct Interrupt *interrupt,
257 struct DevBase *base)
259 return Prm_AddIntServer(card, interrupt);
264 /****i* prism2.device/RemPrometheusIntServer *******************************
266 * NAME
267 * RemPrometheusIntServer
269 * SYNOPSIS
270 * RemPrometheusIntServer()
272 * VOID RemPrometheusIntServer(ULONG);
274 ****************************************************************************
278 VOID RemPrometheusIntServer(APTR card, struct Interrupt *interrupt,
279 struct DevBase *base)
281 Prm_RemIntServer(card, interrupt);
283 return;