New WPA-capable version of prism2.device.
[AROS.git] / workbench / devs / networks / prism2 / expansion.c
blob6a9214fe211903e6d7abfb0e8ac7425fdde48882
1 /*
3 Copyright (C) 2004-2012 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 <expansion/pci.h>
26 #include <proto/exec.h>
27 #include <proto/expansion.h>
29 #include "pci.h"
30 #include "plx9052.h"
31 #include "prism2.h"
33 #include "pci_protos.h"
34 #include "expansion_protos.h"
35 #include "timer_protos.h"
38 /* Private prototypes */
40 static VOID WordsInIOHook(struct BusContext *context, ULONG offset,
41 UWORD *buffer, ULONG count);
42 static VOID WordsOutIOHook(struct BusContext *context, ULONG offset,
43 const UWORD *buffer, ULONG count);
44 static VOID BEWordOutIOHook(struct BusContext *context, ULONG offset,
45 UWORD value);
46 static UWORD LEWordInIOHook(struct BusContext *context, ULONG offset);
47 static VOID LEWordOutIOHook(struct BusContext *context, ULONG offset,
48 UWORD value);
51 IMPORT const UWORD product_codes[];
54 static const struct TagItem bridge_unit_tags[] =
56 {IOTAG_WordsIn, (UPINT)WordsInIOHook},
57 {IOTAG_WordsOut, (UPINT)WordsOutIOHook},
58 {IOTAG_BEWordOut, (UPINT)BEWordOutIOHook},
59 {IOTAG_LEWordIn, (UPINT)LEWordInIOHook},
60 {IOTAG_LEWordOut, (UPINT)LEWordOutIOHook},
61 {TAG_END, 0}
65 /****i* prism2.device/GetExpansionCount ************************************
67 * NAME
68 * GetExpansionCount -- Get the number of compatible PCI Cards.
70 * SYNOPSIS
71 * count = GetExpansionCount()
73 * ULONG GetExpansionCount();
75 ****************************************************************************
79 ULONG GetExpansionCount(struct DevBase *base)
81 ULONG count = 0;
82 struct PCIDevice *card;
84 if(base->i_pci != NULL)
86 while((card =
87 base->i_pci->FindDeviceTags(FDT_CandidateList, product_codes,
88 FDT_Index, count, TAG_END)) != NULL)
90 base->i_pci->FreeDevice(card);
91 count++;
95 return count;
100 /****i* prism2.device/AllocExpansionCard ***********************************
102 * NAME
103 * AllocExpansionCard
105 * SYNOPSIS
106 * context = AllocExpansionCard(index)
108 * struct BusContext *AllocExpansionCard(ULONG);
110 ****************************************************************************
114 struct BusContext *AllocExpansionCard(ULONG index, struct DevBase *base)
116 BOOL success = TRUE;
117 struct BusContext *context;
118 struct PCIDevice *card = NULL;
119 struct PCIResourceRange *io_range = NULL;
120 UBYTE io_range_no;
121 ULONG value;
122 UPINT int_reg;
123 volatile UBYTE *cor_reg;
125 /* Find a compatible card */
127 context = AllocMem(sizeof(struct BusContext), MEMF_PUBLIC | MEMF_CLEAR);
128 if(context == NULL)
129 success = FALSE;
131 if(success)
133 context->card = card =
134 base->i_pci->FindDeviceTags(FDT_CandidateList, product_codes,
135 FDT_Index, index, TAG_END);
136 if(card == NULL)
137 success = FALSE;
140 /* Lock card */
142 if(success)
143 success = card->Lock(PCI_LOCK_EXCLUSIVE);
145 if(success)
147 /* Find out what type of Prism II PCI card this is */
149 card->SetEndian(PCI_MODE_BIG_ENDIAN);
150 context->bus_type = GetBusType(card->ReadConfigWord(PCI_DEVICE_ID),
151 base);
153 if(context->bus_type == TMD_BUS)
155 /* Reset and enable the PCCard */
157 io_range = card->GetResourceRange(1);
158 card->OutByte(io_range->BaseAddress, COR_RESET);
159 BusyMilliDelay(RESET_DELAY, base);
160 card->OutByte(io_range->BaseAddress, COR_ENABLE);
161 BusyMilliDelay(RESET_DELAY, base);
162 card->FreeResourceRange(io_range);
163 io_range_no = 2;
164 context->unit_tags = bridge_unit_tags;
166 else if(context->bus_type == PLX_BUS)
168 /* Reset and enable the PCCard */
170 io_range = card->GetResourceRange(2);
171 cor_reg = (volatile UBYTE *)io_range->BaseAddress + 0x3e0;
172 *cor_reg = COR_ENABLE;
173 BusyMilliDelay(RESET_DELAY, base);
174 card->FreeResourceRange(io_range);
176 /* Enable interrupts on the bridge */
178 io_range = card->GetResourceRange(1);
179 int_reg = io_range->BaseAddress + PLX9052_INTS;
180 card->FreeResourceRange(io_range);
181 value = card->InLong(int_reg);
182 card->OutLong(int_reg, value | (1 << 6));
183 if((card->InLong(int_reg) & (1 << 6)) == 0)
184 success = FALSE;
185 io_range_no = 3;
186 context->unit_tags = bridge_unit_tags;
188 else
190 card->WriteConfigWord(PCI_COMMAND, PCI_COMMAND_MEMORY);
191 /* For PegII */
192 io_range_no = 0;
195 /* Get the I/O base of the wireless chip */
197 context->have_card = TRUE;
198 card->SetEndian(PCI_MODE_LITTLE_ENDIAN);
199 io_range = card->GetResourceRange(io_range_no);
200 context->io_base = io_range->BaseAddress;
201 card->FreeResourceRange(io_range);
203 if(context->bus_type == PCI_BUS)
205 /* Reset and enable the card */
207 cor_reg = (volatile UBYTE *)context->io_base + (P2_REG_PCICOR * 2);
208 *cor_reg = COR_RESET;
209 BusyMilliDelay(250, base);
210 *cor_reg = 0;
211 BusyMilliDelay(500, base);
215 if(!success)
217 FreeExpansionCard(context, base);
218 context = NULL;
221 return context;
226 /****i* prism2.device/FreeExpansionCard ************************************
228 * NAME
229 * FreeExpansionCard
231 * SYNOPSIS
232 * FreeExpansionCard(context)
234 * VOID FreeExpansionCard(struct BusContext *);
236 ****************************************************************************
240 VOID FreeExpansionCard(struct BusContext *context, struct DevBase *base)
242 struct PCIDevice *card;
243 struct PCIResourceRange *io_range = NULL;
244 ULONG value;
245 UPINT int_reg;
246 volatile UBYTE *cor_reg;
248 if(context != NULL)
250 card = context->card;
251 if(card != NULL)
253 if(context->bus_type == TMD_BUS)
255 /* Disable the PCCard */
257 io_range = card->GetResourceRange(1);
258 card->OutByte(io_range->BaseAddress, 0);
259 card->FreeResourceRange(io_range);
261 else if(context->bus_type == PLX_BUS)
263 /* Disable interrupts on the bridge */
265 io_range = card->GetResourceRange(1);
266 int_reg = io_range->BaseAddress + PLX9052_INTS;
267 card->FreeResourceRange(io_range);
268 value = card->InLong(int_reg);
269 card->OutLong(int_reg, value & ~(1 << 6));
271 /* Disable the PCCard */
273 io_range = card->GetResourceRange(2);
274 cor_reg = (volatile UBYTE *)io_range->BaseAddress + 0x3e0;
275 *cor_reg = COR_RESET;
276 BusyMilliDelay(250, base);
277 *cor_reg = 0;
279 card->FreeResourceRange(io_range);
282 if(context->have_card)
283 card->Unlock();
284 base->i_pci->FreeDevice(card);
285 FreeMem(context, sizeof(struct BusContext));
289 return;
294 /****i* prism2.device/AddExpansionIntServer ********************************
296 * NAME
297 * AddExpansionIntServer
299 * SYNOPSIS
300 * success = AddExpansionIntServer(card, interrupt)
302 * BOOL AddExpansionIntServer(APTR, struct Interrupt *);
304 ****************************************************************************
308 BOOL AddExpansionIntServer(APTR card, struct Interrupt *interrupt,
309 struct DevBase *base)
311 return AddIntServer(((struct PCIDevice *)card)->MapInterrupt(),
312 interrupt);
317 /****i* prism2.device/RemExpansionIntServer ********************************
319 * NAME
320 * RemExpansionIntServer
322 * SYNOPSIS
323 * RemExpansionIntServer(card, interrupt)
325 * VOID RemExpansionIntServer(APTR, struct Interrupt *);
327 ****************************************************************************
331 VOID RemExpansionIntServer(APTR card, struct Interrupt *interrupt,
332 struct DevBase *base)
334 RemIntServer(((struct PCIDevice *)card)->MapInterrupt(), interrupt);
336 return;
341 /****i* prism2.device/WordsInIOHook ****************************************
343 * NAME
344 * WordsInIOHook
346 * SYNOPSIS
347 * WordsInIOHook(context, offset, buffer, count)
349 * VOID WordsInIOHook(struct BusContext *, ULONG, UWORD *, ULONG);
351 ****************************************************************************
355 static VOID WordsInIOHook(struct BusContext *context, ULONG offset,
356 UWORD *buffer, ULONG count)
358 struct PCIDevice *card;
360 card = context->card;
361 while(count-- > 0)
362 *buffer++ = card->InWord(context->io_base + offset);
364 return;
369 /****i* prism2.device/WordsOutIOHook ***************************************
371 * NAME
372 * WordsOutIOHook
374 * SYNOPSIS
375 * WordsOutIOHook(context, offset, buffer,
376 * count)
378 * VOID WordsOutIOHook(struct BusContext *, ULONG, const UWORD *,
379 * ULONG);
381 ****************************************************************************
385 static VOID WordsOutIOHook(struct BusContext *context, ULONG offset,
386 const UWORD *buffer, ULONG count)
388 struct PCIDevice *card;
390 card = context->card;
391 while(count-- > 0)
392 card->OutWord(context->io_base + offset, *buffer++);
394 return;
399 /****i* prism2.device/BEWordOutIOHook **************************************
401 * NAME
402 * BEWordOutIOHook
404 * SYNOPSIS
405 * BEWordOutIOHook(context, offset, value)
407 * VOID BEWordOutIOHook(struct BusContext *, ULONG, UWORD);
409 ****************************************************************************
413 static VOID BEWordOutIOHook(struct BusContext *context, ULONG offset,
414 UWORD value)
416 struct PCIDevice *card;
418 card = context->card;
419 card->OutWord(context->io_base + offset, MakeBEWord(value));
421 return;
426 /****i* prism2.device/LEWordInIOHook ***************************************
428 * NAME
429 * LEWordInIOHook
431 * SYNOPSIS
432 * value = LEWordInIOHook(context, offset)
434 * UWORD LEWordInIOHook(struct BusContext *, ULONG);
436 ****************************************************************************
440 static UWORD LEWordInIOHook(struct BusContext *context, ULONG offset)
442 struct PCIDevice *card;
444 card = context->card;
445 return LEWord(card->InWord(context->io_base + offset));
450 /****i* prism2.device/LEWordOutIOHook **************************************
452 * NAME
453 * LEWordOutIOHook
455 * SYNOPSIS
456 * LEWordOutIOHook(context, offset, value)
458 * VOID LEWordOutIOHook(struct BusContext *, ULONG, UWORD);
460 ****************************************************************************
464 static VOID LEWordOutIOHook(struct BusContext *context, ULONG offset,
465 UWORD value)
467 struct PCIDevice *card;
469 card = context->card;
470 card->OutWord(context->io_base + offset, MakeLEWord(value));
472 return;