New WPA-capable version of prism2.device.
[AROS.git] / workbench / devs / networks / prism2 / openpci.c
blob9ea078f20110591d2eb2d4d1b7d53b8a87983356
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 <libraries/openpci.h>
26 #include <proto/exec.h>
27 #include <proto/openpci.h>
29 #include "pci.h"
30 #include "plx9052.h"
31 #include "prism2.h"
33 #include "pci_protos.h"
34 #include "openpci_protos.h"
35 #include "timer_protos.h"
38 /****i* prism2.device/GetOpenPCICount **************************************
40 * NAME
41 * GetOpenPCICount
43 * SYNOPSIS
44 * count = GetOpenPCICount()
46 * ULONG GetOpenPCICount();
48 ****************************************************************************
52 ULONG GetOpenPCICount(struct DevBase *base)
54 ULONG count = 0;
55 struct pci_dev *card = NULL;
56 UWORD vendor_id, product_id;
58 while((card = pci_find_device(0xffff, 0xffff, card)) != NULL)
60 product_id = pci_read_config_word(PCI_DEVICE_ID, card);
61 vendor_id = pci_read_config_word(PCI_VENDOR_ID, card);
62 if(IsCardCompatible(vendor_id, product_id, base))
63 count++;
66 return count;
71 /****i* prism2.device/AllocOpenPCICard *************************************
73 * NAME
74 * AllocOpenPCICard -- Create a unit.
76 * SYNOPSIS
77 * context = AllocOpenPCICard(index)
79 * struct BusContext *AllocOpenPCICard(ULONG);
81 ****************************************************************************
85 struct BusContext *AllocOpenPCICard(ULONG index, struct DevBase *base)
87 BOOL success = TRUE;
88 struct BusContext *context;
89 struct pci_dev *card = NULL;
90 UWORD i = 0, vendor_id, product_id, io_range_no;
91 ULONG value;
92 UPINT io_reg, int_reg;
93 volatile UBYTE *cor_reg;
95 /* Find a compatible card */
97 context = AllocMem(sizeof(struct BusContext), MEMF_PUBLIC | MEMF_CLEAR);
98 if(context == NULL)
99 success = FALSE;
101 if(success)
103 while(i <= index)
105 card = pci_find_device(0xffff, 0xffff, card);
106 product_id = pci_read_config_word(PCI_DEVICE_ID, card);
107 vendor_id = pci_read_config_word(PCI_VENDOR_ID, card);
108 if(IsCardCompatible(vendor_id, product_id, base))
109 i++;
112 context->card = card;
113 if(card == NULL)
114 success = FALSE;
117 if(success)
119 /* Find out what type of Prism II PCI card this is */
121 context->bus_type = GetBusType(product_id, base);
122 pci_write_config_word(PCI_COMMAND,
123 PCI_COMMAND_MEMORY | PCI_COMMAND_IO, card);
125 if(context->bus_type == TMD_BUS)
127 /* Reset and enable the PCCard */
129 io_reg = (UPINT)card->base_address[1];
130 BYTEOUT(io_reg, COR_RESET);
131 BusyMilliDelay(RESET_DELAY, base);
132 BYTEOUT(io_reg, COR_ENABLE);
133 BusyMilliDelay(RESET_DELAY, base);
134 io_range_no = 2;
136 else if(context->bus_type == PLX_BUS)
138 /* Reset and enable the PCCard */
140 cor_reg = (volatile UBYTE *)card->base_address[2] + 0x3e0;
141 *cor_reg = COR_ENABLE;
142 BusyMilliDelay(RESET_DELAY, base);
144 /* Enable interrupts on the bridge */
146 int_reg = (UPINT)card->base_address[1] + PLX9052_INTS;
147 value = LONGIN(int_reg);
148 LONGOUT(int_reg, value | (1 << 6));
149 if((LONGIN(int_reg) & (1 << 6)) == 0)
150 success = FALSE;
151 io_range_no = 3;
153 else
154 io_range_no = 0;
156 /* Get the I/O base of the wireless chip */
158 context->have_card = TRUE;
159 context->io_base = (UPINT)card->base_address[io_range_no];
161 if(context->bus_type == PCI_BUS)
163 /* Reset and enable the card */
165 cor_reg = (volatile UBYTE *)context->io_base + (P2_REG_PCICOR * 2);
166 *cor_reg = COR_RESET;
167 BusyMilliDelay(250, base);
168 *cor_reg = 0;
169 BusyMilliDelay(500, base);
173 if(!success)
175 FreeOpenPCICard(context, base);
176 context = NULL;
179 return context;
184 /****i* prism2.device/FreeOpenPCICard **************************************
186 * NAME
187 * FreeOpenPCICard
189 * SYNOPSIS
190 * FreeOpenPCICard(context)
192 * VOID FreeOpenPCICard(struct BusContext *);
194 ****************************************************************************
198 VOID FreeOpenPCICard(struct BusContext *context, struct DevBase *base)
200 struct pci_dev *card;
202 ULONG value;
203 UPINT io_reg, int_reg;
204 volatile UBYTE *cor_reg;
206 if(context != NULL)
208 card = context->card;
209 if(card != NULL)
211 if(context->bus_type == TMD_BUS)
213 /* Disable the PCCard */
215 io_reg = (UPINT)card->base_address[1];
216 BYTEOUT(io_reg, 0);
218 else if(context->bus_type == PLX_BUS)
220 /* Disable interrupts on the bridge */
222 int_reg = (UPINT)card->base_address[1] + PLX9052_INTS;
223 value = LONGIN(int_reg);
224 LONGOUT(int_reg, value & ~(1 << 6));
226 /* Disable the PCCard */
228 cor_reg = (volatile UBYTE *)card->base_address[2] + 0x3e0;
229 *cor_reg = COR_RESET;
230 BusyMilliDelay(250, base);
231 *cor_reg = 0;
234 FreeMem(context, sizeof(struct BusContext));
238 return;
243 /****i* prism2.device/AddOpenPCIIntServer **********************************
245 * NAME
246 * AddOpenPCIIntServer
248 * SYNOPSIS
249 * success = AddOpenPCIIntServer(card, interrupt)
251 * BOOL AddOpenPCIIntServer(APTR, struct Interrupt *);
253 ****************************************************************************
257 BOOL AddOpenPCIIntServer(APTR card, struct Interrupt *interrupt,
258 struct DevBase *base)
260 return pci_add_intserver(interrupt, card);
265 /****i* prism2.device/RemOpenPCIIntServer **********************************
267 * NAME
268 * RemOpenPCIIntServer
270 * SYNOPSIS
271 * RemOpenPCIIntServer(card, interrupt)
273 * VOID RemOpenPCIIntServer(APTR, struct Interrupt *);
275 ****************************************************************************
279 VOID RemOpenPCIIntServer(APTR card, struct Interrupt *interrupt,
280 struct DevBase *base)
282 pci_rem_intserver(interrupt, card);
284 return;