1 |
1275 |
phoenix |
/*======================================================================
|
2 |
|
|
|
3 |
|
|
Cardbus device configuration
|
4 |
|
|
|
5 |
|
|
cardbus.c 1.87 2002/10/24 06:11:41
|
6 |
|
|
|
7 |
|
|
The contents of this file are subject to the Mozilla Public
|
8 |
|
|
License Version 1.1 (the "License"); you may not use this file
|
9 |
|
|
except in compliance with the License. You may obtain a copy of
|
10 |
|
|
the License at http://www.mozilla.org/MPL/
|
11 |
|
|
|
12 |
|
|
Software distributed under the License is distributed on an "AS
|
13 |
|
|
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
14 |
|
|
implied. See the License for the specific language governing
|
15 |
|
|
rights and limitations under the License.
|
16 |
|
|
|
17 |
|
|
The initial developer of the original code is David A. Hinds
|
18 |
|
|
<dahinds@users.sourceforge.net>. Portions created by David A. Hinds
|
19 |
|
|
are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
|
20 |
|
|
|
21 |
|
|
Alternatively, the contents of this file may be used under the
|
22 |
|
|
terms of the GNU General Public License version 2 (the "GPL"), in which
|
23 |
|
|
case the provisions of the GPL are applicable instead of the
|
24 |
|
|
above. If you wish to allow the use of your version of this file
|
25 |
|
|
only under the terms of the GPL and not to allow others to use
|
26 |
|
|
your version of this file under the MPL, indicate your decision
|
27 |
|
|
by deleting the provisions above and replace them with the notice
|
28 |
|
|
and other provisions required by the GPL. If you do not delete
|
29 |
|
|
the provisions above, a recipient may use your version of this
|
30 |
|
|
file under either the MPL or the GPL.
|
31 |
|
|
|
32 |
|
|
These routines handle allocating resources for Cardbus cards, as
|
33 |
|
|
well as setting up and shutting down Cardbus sockets. They are
|
34 |
|
|
called from cs.c in response to Request/ReleaseConfiguration and
|
35 |
|
|
Request/ReleaseIO calls.
|
36 |
|
|
|
37 |
|
|
======================================================================*/
|
38 |
|
|
|
39 |
|
|
/*
|
40 |
|
|
* This file is going away. Cardbus handling has been re-written to be
|
41 |
|
|
* more of a PCI bridge thing, and the PCI code basically does all the
|
42 |
|
|
* resource handling. This has wrappers to make the rest of the PCMCIA
|
43 |
|
|
* subsystem not notice that it's not here any more.
|
44 |
|
|
*
|
45 |
|
|
* Linus, Jan 2000
|
46 |
|
|
*/
|
47 |
|
|
|
48 |
|
|
|
49 |
|
|
#define __NO_VERSION__
|
50 |
|
|
|
51 |
|
|
#include <linux/module.h>
|
52 |
|
|
#include <linux/kernel.h>
|
53 |
|
|
#include <linux/string.h>
|
54 |
|
|
#include <linux/slab.h>
|
55 |
|
|
#include <linux/mm.h>
|
56 |
|
|
#include <linux/pci.h>
|
57 |
|
|
#include <linux/ioport.h>
|
58 |
|
|
#include <asm/irq.h>
|
59 |
|
|
#include <asm/io.h>
|
60 |
|
|
|
61 |
|
|
#define IN_CARD_SERVICES
|
62 |
|
|
#include <pcmcia/version.h>
|
63 |
|
|
#include <pcmcia/cs_types.h>
|
64 |
|
|
#include <pcmcia/ss.h>
|
65 |
|
|
#include <pcmcia/cs.h>
|
66 |
|
|
#include <pcmcia/bulkmem.h>
|
67 |
|
|
#include <pcmcia/cistpl.h>
|
68 |
|
|
#include "cs_internal.h"
|
69 |
|
|
|
70 |
|
|
#ifdef PCMCIA_DEBUG
|
71 |
|
|
static int pc_debug = PCMCIA_DEBUG;
|
72 |
|
|
#endif
|
73 |
|
|
|
74 |
|
|
/*====================================================================*/
|
75 |
|
|
|
76 |
|
|
#define FIND_FIRST_BIT(n) ((n) - ((n) & ((n)-1)))
|
77 |
|
|
|
78 |
|
|
#define pci_readb pci_read_config_byte
|
79 |
|
|
#define pci_writeb pci_write_config_byte
|
80 |
|
|
#define pci_readw pci_read_config_word
|
81 |
|
|
#define pci_writew pci_write_config_word
|
82 |
|
|
#define pci_readl pci_read_config_dword
|
83 |
|
|
#define pci_writel pci_write_config_dword
|
84 |
|
|
|
85 |
|
|
/* Offsets in the Expansion ROM Image Header */
|
86 |
|
|
#define ROM_SIGNATURE 0x0000 /* 2 bytes */
|
87 |
|
|
#define ROM_DATA_PTR 0x0018 /* 2 bytes */
|
88 |
|
|
|
89 |
|
|
/* Offsets in the CardBus PC Card Data Structure */
|
90 |
|
|
#define PCDATA_SIGNATURE 0x0000 /* 4 bytes */
|
91 |
|
|
#define PCDATA_VPD_PTR 0x0008 /* 2 bytes */
|
92 |
|
|
#define PCDATA_LENGTH 0x000a /* 2 bytes */
|
93 |
|
|
#define PCDATA_REVISION 0x000c
|
94 |
|
|
#define PCDATA_IMAGE_SZ 0x0010 /* 2 bytes */
|
95 |
|
|
#define PCDATA_ROM_LEVEL 0x0012 /* 2 bytes */
|
96 |
|
|
#define PCDATA_CODE_TYPE 0x0014
|
97 |
|
|
#define PCDATA_INDICATOR 0x0015
|
98 |
|
|
|
99 |
|
|
typedef struct cb_config_t {
|
100 |
|
|
struct pci_dev dev;
|
101 |
|
|
} cb_config_t;
|
102 |
|
|
|
103 |
|
|
/*=====================================================================
|
104 |
|
|
|
105 |
|
|
Expansion ROM's have a special layout, and pointers specify an
|
106 |
|
|
image number and an offset within that image. xlate_rom_addr()
|
107 |
|
|
converts an image/offset address to an absolute offset from the
|
108 |
|
|
ROM's base address.
|
109 |
|
|
|
110 |
|
|
=====================================================================*/
|
111 |
|
|
|
112 |
|
|
static u_int xlate_rom_addr(u_char * b, u_int addr)
|
113 |
|
|
{
|
114 |
|
|
u_int img = 0, ofs = 0, sz;
|
115 |
|
|
u_short data;
|
116 |
|
|
while ((readb(b) == 0x55) && (readb(b + 1) == 0xaa)) {
|
117 |
|
|
if (img == (addr >> 28))
|
118 |
|
|
return (addr & 0x0fffffff) + ofs;
|
119 |
|
|
data = readb(b + ROM_DATA_PTR) + (readb(b + ROM_DATA_PTR + 1) << 8);
|
120 |
|
|
sz = 512 * (readb(b + data + PCDATA_IMAGE_SZ) +
|
121 |
|
|
(readb(b + data + PCDATA_IMAGE_SZ + 1) << 8));
|
122 |
|
|
if ((sz == 0) || (readb(b + data + PCDATA_INDICATOR) & 0x80))
|
123 |
|
|
break;
|
124 |
|
|
b += sz;
|
125 |
|
|
ofs += sz;
|
126 |
|
|
img++;
|
127 |
|
|
}
|
128 |
|
|
return 0;
|
129 |
|
|
}
|
130 |
|
|
|
131 |
|
|
/*=====================================================================
|
132 |
|
|
|
133 |
|
|
These are similar to setup_cis_mem and release_cis_mem for 16-bit
|
134 |
|
|
cards. The "result" that is used externally is the cb_cis_virt
|
135 |
|
|
pointer in the socket_info_t structure.
|
136 |
|
|
|
137 |
|
|
=====================================================================*/
|
138 |
|
|
|
139 |
|
|
void cb_release_cis_mem(socket_info_t * s)
|
140 |
|
|
{
|
141 |
|
|
if (s->cb_cis_virt) {
|
142 |
|
|
DEBUG(1, "cs: cb_release_cis_mem()\n");
|
143 |
|
|
iounmap(s->cb_cis_virt);
|
144 |
|
|
s->cb_cis_virt = NULL;
|
145 |
|
|
s->cb_cis_res = 0;
|
146 |
|
|
}
|
147 |
|
|
}
|
148 |
|
|
|
149 |
|
|
static int cb_setup_cis_mem(socket_info_t * s, struct pci_dev *dev, struct resource *res)
|
150 |
|
|
{
|
151 |
|
|
unsigned int start, size;
|
152 |
|
|
|
153 |
|
|
if (res == s->cb_cis_res)
|
154 |
|
|
return 0;
|
155 |
|
|
|
156 |
|
|
if (s->cb_cis_res)
|
157 |
|
|
cb_release_cis_mem(s);
|
158 |
|
|
|
159 |
|
|
start = res->start;
|
160 |
|
|
size = res->end - start + 1;
|
161 |
|
|
s->cb_cis_virt = ioremap(start, size);
|
162 |
|
|
|
163 |
|
|
if (!s->cb_cis_virt)
|
164 |
|
|
return -1;
|
165 |
|
|
|
166 |
|
|
s->cb_cis_res = res;
|
167 |
|
|
|
168 |
|
|
return 0;
|
169 |
|
|
}
|
170 |
|
|
|
171 |
|
|
/*=====================================================================
|
172 |
|
|
|
173 |
|
|
This is used by the CIS processing code to read CIS information
|
174 |
|
|
from a CardBus device.
|
175 |
|
|
|
176 |
|
|
=====================================================================*/
|
177 |
|
|
|
178 |
|
|
int read_cb_mem(socket_info_t * s, u_char fn, int space,
|
179 |
|
|
u_int addr, u_int len, void *ptr)
|
180 |
|
|
{
|
181 |
|
|
struct pci_dev *dev;
|
182 |
|
|
struct resource *res;
|
183 |
|
|
|
184 |
|
|
DEBUG(3, "cs: read_cb_mem(%d, %#x, %u)\n", space, addr, len);
|
185 |
|
|
|
186 |
|
|
if (!s->cb_config)
|
187 |
|
|
goto fail;
|
188 |
|
|
|
189 |
|
|
dev = &s->cb_config[fn].dev;
|
190 |
|
|
|
191 |
|
|
/* Config space? */
|
192 |
|
|
if (space == 0) {
|
193 |
|
|
if (addr + len > 0x100)
|
194 |
|
|
goto fail;
|
195 |
|
|
for (; len; addr++, ptr++, len--)
|
196 |
|
|
pci_readb(dev, addr, (u_char *) ptr);
|
197 |
|
|
return 0;
|
198 |
|
|
}
|
199 |
|
|
|
200 |
|
|
res = dev->resource + space - 1;
|
201 |
|
|
if (!res->flags)
|
202 |
|
|
goto fail;
|
203 |
|
|
|
204 |
|
|
if (cb_setup_cis_mem(s, dev, res) != 0)
|
205 |
|
|
goto fail;
|
206 |
|
|
|
207 |
|
|
if (space == 7) {
|
208 |
|
|
addr = xlate_rom_addr(s->cb_cis_virt, addr);
|
209 |
|
|
if (addr == 0)
|
210 |
|
|
goto fail;
|
211 |
|
|
}
|
212 |
|
|
|
213 |
|
|
if (addr + len > res->end - res->start)
|
214 |
|
|
goto fail;
|
215 |
|
|
|
216 |
|
|
memcpy_fromio(ptr, s->cb_cis_virt + addr, len);
|
217 |
|
|
return 0;
|
218 |
|
|
|
219 |
|
|
fail:
|
220 |
|
|
memset(ptr, 0xff, len);
|
221 |
|
|
return -1;
|
222 |
|
|
}
|
223 |
|
|
|
224 |
|
|
struct pci_dev *cb_scan_slot(struct pci_dev *temp, struct list_head *list)
|
225 |
|
|
{
|
226 |
|
|
struct pci_dev *dev;
|
227 |
|
|
struct pci_dev *first_dev = NULL;
|
228 |
|
|
int func = 0;
|
229 |
|
|
int is_multi = 0;
|
230 |
|
|
u8 hdr_type;
|
231 |
|
|
|
232 |
|
|
for (func = 0; func < 8; func++, temp->devfn++) {
|
233 |
|
|
if (func && !is_multi) /* not a multi-function device */
|
234 |
|
|
continue;
|
235 |
|
|
if (pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type))
|
236 |
|
|
continue;
|
237 |
|
|
temp->hdr_type = hdr_type & 0x7f;
|
238 |
|
|
|
239 |
|
|
dev = pci_scan_device(temp);
|
240 |
|
|
if (!dev)
|
241 |
|
|
continue;
|
242 |
|
|
sprintf(dev->name, "PCI device %04x:%04x", dev->vendor, dev->device);
|
243 |
|
|
if (!func) {
|
244 |
|
|
is_multi = hdr_type & 0x80;
|
245 |
|
|
first_dev = dev;
|
246 |
|
|
}
|
247 |
|
|
|
248 |
|
|
list_add_tail(&dev->global_list, list);
|
249 |
|
|
/* Fix up broken headers */
|
250 |
|
|
//FIXME pci_fixup_device(PCI_FIXUP_HEADER, dev);
|
251 |
|
|
}
|
252 |
|
|
return first_dev;
|
253 |
|
|
}
|
254 |
|
|
|
255 |
|
|
static unsigned int cb_scan_new_bus(struct pci_bus *bus, int irq);
|
256 |
|
|
|
257 |
|
|
static int cb_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int irq)
|
258 |
|
|
{
|
259 |
|
|
unsigned int buses;
|
260 |
|
|
unsigned short cr;
|
261 |
|
|
struct pci_bus *child;
|
262 |
|
|
int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS);
|
263 |
|
|
|
264 |
|
|
pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);
|
265 |
|
|
printk("Scanning behind PCI bridge %s, config %06x\n", dev->slot_name, buses & 0xffffff);
|
266 |
|
|
/*
|
267 |
|
|
* We need to assign a number to this bus which we always
|
268 |
|
|
* do in the second pass. We also keep all address decoders
|
269 |
|
|
* on the bridge disabled during scanning. FIXME: Why?
|
270 |
|
|
*/
|
271 |
|
|
pci_read_config_word(dev, PCI_COMMAND, &cr);
|
272 |
|
|
pci_write_config_word(dev, PCI_COMMAND, 0x0000);
|
273 |
|
|
pci_write_config_word(dev, PCI_STATUS, 0xffff);
|
274 |
|
|
|
275 |
|
|
child = pci_add_new_bus(bus, dev, ++max);
|
276 |
|
|
buses = (buses & 0xff000000)
|
277 |
|
|
| ((unsigned int)(child->primary) << 0)
|
278 |
|
|
| ((unsigned int)(child->secondary) << 8)
|
279 |
|
|
| ((unsigned int)(child->subordinate) << 16);
|
280 |
|
|
/*
|
281 |
|
|
* We need to blast all three values with a single write.
|
282 |
|
|
*/
|
283 |
|
|
pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses);
|
284 |
|
|
if (!is_cardbus) {
|
285 |
|
|
/* Now we can scan all subordinate buses... */
|
286 |
|
|
max = cb_scan_new_bus(child, irq);
|
287 |
|
|
} else {
|
288 |
|
|
/*
|
289 |
|
|
* For CardBus bridges, we leave 4 bus numbers
|
290 |
|
|
* as cards with a PCI-to-PCI bridge can be
|
291 |
|
|
* inserted later.
|
292 |
|
|
*/
|
293 |
|
|
max += 3;
|
294 |
|
|
}
|
295 |
|
|
/*
|
296 |
|
|
* Set the subordinate bus number to its real value.
|
297 |
|
|
*/
|
298 |
|
|
child->subordinate = max;
|
299 |
|
|
pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);
|
300 |
|
|
pci_write_config_word(dev, PCI_COMMAND, cr);
|
301 |
|
|
sprintf(child->name, (is_cardbus ? "PCI CardBus #%02x" : "PCI Bus #%02x"), child->number);
|
302 |
|
|
return max;
|
303 |
|
|
}
|
304 |
|
|
|
305 |
|
|
static unsigned int cb_scan_new_bus(struct pci_bus *bus, int irq)
|
306 |
|
|
{
|
307 |
|
|
unsigned int devfn, max;
|
308 |
|
|
struct list_head *ln, *ln_tmp;
|
309 |
|
|
struct pci_dev *dev, dev0;
|
310 |
|
|
struct list_head found;
|
311 |
|
|
|
312 |
|
|
INIT_LIST_HEAD(&found);
|
313 |
|
|
|
314 |
|
|
printk("Scanning bus %02x\n", bus->number);
|
315 |
|
|
max = bus->secondary;
|
316 |
|
|
|
317 |
|
|
/* Create a device template */
|
318 |
|
|
memset(&dev0, 0, sizeof(dev0));
|
319 |
|
|
dev0.bus = bus;
|
320 |
|
|
dev0.sysdata = bus->sysdata;
|
321 |
|
|
|
322 |
|
|
/* Go find them, Rover! */
|
323 |
|
|
for (devfn = 0; devfn < 0x100; devfn += 8) {
|
324 |
|
|
dev0.devfn = devfn;
|
325 |
|
|
cb_scan_slot(&dev0, &found);
|
326 |
|
|
}
|
327 |
|
|
|
328 |
|
|
/*
|
329 |
|
|
* After performing arch-dependent fixup of the bus, look behind
|
330 |
|
|
* all PCI-to-PCI bridges on this bus.
|
331 |
|
|
*/
|
332 |
|
|
printk("Fixups for bus %02x\n", bus->number);
|
333 |
|
|
pci_read_bridge_bases(bus);
|
334 |
|
|
|
335 |
|
|
list_for_each_safe(ln, ln_tmp, &found)
|
336 |
|
|
{
|
337 |
|
|
int i;
|
338 |
|
|
u8 irq_pin;
|
339 |
|
|
dev = pci_dev_g(ln);
|
340 |
|
|
pci_set_power_state(dev, 0);
|
341 |
|
|
for(i=0;i<6;i++)
|
342 |
|
|
{
|
343 |
|
|
struct resource *r = dev->resource + i;
|
344 |
|
|
if(!r->start && r->end)
|
345 |
|
|
pci_assign_resource(dev, i);
|
346 |
|
|
}
|
347 |
|
|
/* Does this function have an interrupt at all? */
|
348 |
|
|
pci_readb(dev, PCI_INTERRUPT_PIN, &irq_pin);
|
349 |
|
|
if (irq_pin) {
|
350 |
|
|
dev->irq = irq;
|
351 |
|
|
pci_writeb(dev, PCI_INTERRUPT_LINE, irq);
|
352 |
|
|
}
|
353 |
|
|
|
354 |
|
|
pci_enable_device(dev); /* XXX check return */
|
355 |
|
|
pci_insert_device(dev, bus);
|
356 |
|
|
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
|
357 |
|
|
max = cb_scan_bridge(bus, dev, max, irq);
|
358 |
|
|
}
|
359 |
|
|
|
360 |
|
|
/*
|
361 |
|
|
* We've scanned the bus and so we know all about what's on
|
362 |
|
|
* the other side of any bridges that may be on this bus plus
|
363 |
|
|
* any devices.
|
364 |
|
|
*
|
365 |
|
|
* Return how far we've got finding sub-buses.
|
366 |
|
|
*/
|
367 |
|
|
printk("Bus scan for %02x returning with max=%02x\n", bus->number, max);
|
368 |
|
|
return max;
|
369 |
|
|
}
|
370 |
|
|
|
371 |
|
|
static void program_bridge(struct pci_dev *bridge)
|
372 |
|
|
{
|
373 |
|
|
u32 l;
|
374 |
|
|
|
375 |
|
|
/* Set up the top and bottom of the PCI I/O segment for this bus. */
|
376 |
|
|
pci_read_config_dword(bridge, PCI_IO_BASE, &l);
|
377 |
|
|
l &= 0xffff0000;
|
378 |
|
|
l |= (bridge->resource[7].start >> 8) & 0x00f0;
|
379 |
|
|
l |= bridge->resource[7].end & 0xf000;
|
380 |
|
|
pci_write_config_dword(bridge, PCI_IO_BASE, l);
|
381 |
|
|
|
382 |
|
|
/* Clear upper 16 bits of I/O base/limit. */
|
383 |
|
|
pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0);
|
384 |
|
|
|
385 |
|
|
/* Clear out the upper 32 bits of PREF base/limit. */
|
386 |
|
|
pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, 0);
|
387 |
|
|
pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0);
|
388 |
|
|
|
389 |
|
|
/* Set up the top and bottom of the PCI Memory segment
|
390 |
|
|
for this bus. */
|
391 |
|
|
l = (bridge->resource[8].start >> 16) & 0xfff0;
|
392 |
|
|
l |= bridge->resource[8].end & 0xfff00000;
|
393 |
|
|
pci_write_config_dword(bridge, PCI_MEMORY_BASE, l);
|
394 |
|
|
|
395 |
|
|
/* Set up PREF base/limit. */
|
396 |
|
|
l = (bridge->resource[9].start >> 16) & 0xfff0;
|
397 |
|
|
l |= bridge->resource[9].end & 0xfff00000;
|
398 |
|
|
pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
|
399 |
|
|
|
400 |
|
|
/* FIXME - 0x0c if our ISA VGA is behind it. It looks like X
|
401 |
|
|
can handle this itself - CHECK */
|
402 |
|
|
l = 0x04;
|
403 |
|
|
pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, l);
|
404 |
|
|
}
|
405 |
|
|
|
406 |
|
|
|
407 |
|
|
/*=====================================================================
|
408 |
|
|
|
409 |
|
|
cb_alloc() and cb_free() allocate and free the kernel data
|
410 |
|
|
structures for a Cardbus device, and handle the lowest level PCI
|
411 |
|
|
device setup issues.
|
412 |
|
|
|
413 |
|
|
=====================================================================*/
|
414 |
|
|
|
415 |
|
|
int cb_alloc(socket_info_t * s)
|
416 |
|
|
{
|
417 |
|
|
struct pci_bus *bus;
|
418 |
|
|
struct pci_dev tmp;
|
419 |
|
|
u_short vend, v, dev;
|
420 |
|
|
u_char i, hdr, fn;
|
421 |
|
|
cb_config_t *c;
|
422 |
|
|
int irq;
|
423 |
|
|
|
424 |
|
|
bus = s->cap.cb_dev->subordinate;
|
425 |
|
|
memset(&tmp, 0, sizeof(tmp));
|
426 |
|
|
tmp.bus = bus;
|
427 |
|
|
tmp.sysdata = bus->sysdata;
|
428 |
|
|
tmp.devfn = 0;
|
429 |
|
|
|
430 |
|
|
pci_readw(&tmp, PCI_VENDOR_ID, &vend);
|
431 |
|
|
pci_readw(&tmp, PCI_DEVICE_ID, &dev);
|
432 |
|
|
printk(KERN_INFO "cs: cb_alloc(bus %d): vendor 0x%04x, "
|
433 |
|
|
"device 0x%04x\n", bus->number, vend, dev);
|
434 |
|
|
|
435 |
|
|
pci_readb(&tmp, PCI_HEADER_TYPE, &hdr);
|
436 |
|
|
fn = 1;
|
437 |
|
|
if (hdr & 0x80) {
|
438 |
|
|
do {
|
439 |
|
|
tmp.devfn = fn;
|
440 |
|
|
if (pci_readw(&tmp, PCI_VENDOR_ID, &v) || !v || v == 0xffff)
|
441 |
|
|
break;
|
442 |
|
|
fn++;
|
443 |
|
|
} while (fn < 8);
|
444 |
|
|
}
|
445 |
|
|
s->functions = fn;
|
446 |
|
|
|
447 |
|
|
c = kmalloc(fn * sizeof(struct cb_config_t), GFP_ATOMIC);
|
448 |
|
|
if (!c)
|
449 |
|
|
return CS_OUT_OF_RESOURCE;
|
450 |
|
|
memset(c, 0, fn * sizeof(struct cb_config_t));
|
451 |
|
|
|
452 |
|
|
irq = s->cap.pci_irq;
|
453 |
|
|
for (i = 0; i < fn; i++) {
|
454 |
|
|
struct pci_dev *dev = &c[i].dev;
|
455 |
|
|
u8 irq_pin;
|
456 |
|
|
int r;
|
457 |
|
|
|
458 |
|
|
dev->bus = bus;
|
459 |
|
|
dev->sysdata = bus->sysdata;
|
460 |
|
|
dev->devfn = i;
|
461 |
|
|
dev->vendor = vend;
|
462 |
|
|
pci_readw(dev, PCI_DEVICE_ID, &dev->device);
|
463 |
|
|
dev->hdr_type = hdr & 0x7f;
|
464 |
|
|
|
465 |
|
|
pci_setup_device(dev);
|
466 |
|
|
|
467 |
|
|
if(dev->hdr_type == 1)
|
468 |
|
|
{
|
469 |
|
|
int max = bus->secondary;
|
470 |
|
|
int idx;
|
471 |
|
|
struct resource *res, *pres;
|
472 |
|
|
printk(KERN_INFO "Cardbus: Bridge found - we suck.\n");
|
473 |
|
|
pci_read_bridge_bases(bus);
|
474 |
|
|
for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_BRIDGE_RESOURCES + 3; idx++) {
|
475 |
|
|
res = &dev->resource[idx];
|
476 |
|
|
/* This is ugly - pci_read_bridge_bases should have
|
477 |
|
|
done it for us. Need to find out why it doesnt
|
478 |
|
|
before fixing it */
|
479 |
|
|
if(idx == PCI_BRIDGE_RESOURCES)
|
480 |
|
|
res->flags = IORESOURCE_IO | PCI_IO_RANGE_TYPE_32;
|
481 |
|
|
if(idx == PCI_BRIDGE_RESOURCES+1)
|
482 |
|
|
res->flags |= IORESOURCE_MEM;
|
483 |
|
|
if(idx == PCI_BRIDGE_RESOURCES+2)
|
484 |
|
|
res->flags |= IORESOURCE_MEM|IORESOURCE_PREFETCH;
|
485 |
|
|
/* Ignore any existing values in the chip */
|
486 |
|
|
res->start = 0;
|
487 |
|
|
/* Find the parent resource */
|
488 |
|
|
pres = pci_find_parent_resource(dev, res);
|
489 |
|
|
if(!pres)
|
490 |
|
|
{
|
491 |
|
|
printk(KERN_ERR "No parent resource for %lx\n", res->flags);
|
492 |
|
|
continue;
|
493 |
|
|
}
|
494 |
|
|
printk(KERN_ERR "Allocating for type %lx, in bus resource.\n", res->flags);
|
495 |
|
|
/* Hog the entire space */
|
496 |
|
|
res->start = pres->start;
|
497 |
|
|
if(idx != PCI_BRIDGE_RESOURCES)
|
498 |
|
|
res->end = pres->end;
|
499 |
|
|
else /* Still working this out - FIXME */
|
500 |
|
|
res->end = res->start + 255;
|
501 |
|
|
if (!pres || request_resource(pres, res) < 0)
|
502 |
|
|
printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, dev->slot_name);
|
503 |
|
|
}
|
504 |
|
|
program_bridge(dev);
|
505 |
|
|
max = cb_scan_bridge(bus, dev, max, irq);
|
506 |
|
|
printk(KERN_INFO "Cardbus: Bridge scanned.\n");
|
507 |
|
|
}
|
508 |
|
|
else
|
509 |
|
|
{
|
510 |
|
|
/* FIXME: Do we need to enable the expansion ROM? */
|
511 |
|
|
for (r = 0; r < 7; r++) {
|
512 |
|
|
struct resource *res = dev->resource + r;
|
513 |
|
|
if (res->flags)
|
514 |
|
|
pci_assign_resource(dev, r);
|
515 |
|
|
}
|
516 |
|
|
}
|
517 |
|
|
/* Does this function have an interrupt at all? */
|
518 |
|
|
pci_readb(dev, PCI_INTERRUPT_PIN, &irq_pin);
|
519 |
|
|
if (irq_pin) {
|
520 |
|
|
dev->irq = irq;
|
521 |
|
|
pci_writeb(dev, PCI_INTERRUPT_LINE, irq);
|
522 |
|
|
}
|
523 |
|
|
|
524 |
|
|
pci_enable_device(dev); /* XXX check return */
|
525 |
|
|
pci_insert_device(dev, bus);
|
526 |
|
|
}
|
527 |
|
|
|
528 |
|
|
s->cb_config = c;
|
529 |
|
|
s->irq.AssignedIRQ = irq;
|
530 |
|
|
return CS_SUCCESS;
|
531 |
|
|
}
|
532 |
|
|
|
533 |
|
|
void cb_free(socket_info_t * s)
|
534 |
|
|
{
|
535 |
|
|
cb_config_t *c = s->cb_config;
|
536 |
|
|
|
537 |
|
|
if (c) {
|
538 |
|
|
int i;
|
539 |
|
|
|
540 |
|
|
s->cb_config = NULL;
|
541 |
|
|
for (i = 0 ; i < s->functions ; i++)
|
542 |
|
|
pci_remove_device(&c[i].dev);
|
543 |
|
|
|
544 |
|
|
kfree(c);
|
545 |
|
|
printk(KERN_INFO "cs: cb_free(bus %d)\n", s->cap.cb_dev->subordinate->number);
|
546 |
|
|
}
|
547 |
|
|
}
|
548 |
|
|
|
549 |
|
|
/*=====================================================================
|
550 |
|
|
|
551 |
|
|
cb_config() has the job of allocating all system resources that
|
552 |
|
|
a Cardbus card requires. Rather than using the CIS (which seems
|
553 |
|
|
to not always be present), it treats the card as an ordinary PCI
|
554 |
|
|
device, and probes the base address registers to determine each
|
555 |
|
|
function's IO and memory space needs.
|
556 |
|
|
|
557 |
|
|
It is called from the RequestIO card service.
|
558 |
|
|
|
559 |
|
|
======================================================================*/
|
560 |
|
|
|
561 |
|
|
int cb_config(socket_info_t * s)
|
562 |
|
|
{
|
563 |
|
|
return CS_SUCCESS;
|
564 |
|
|
}
|
565 |
|
|
|
566 |
|
|
/*======================================================================
|
567 |
|
|
|
568 |
|
|
cb_release() releases all the system resources (IO and memory
|
569 |
|
|
space, and interrupt) committed for a Cardbus card by a prior call
|
570 |
|
|
to cb_config().
|
571 |
|
|
|
572 |
|
|
It is called from the ReleaseIO() service.
|
573 |
|
|
|
574 |
|
|
======================================================================*/
|
575 |
|
|
|
576 |
|
|
void cb_release(socket_info_t * s)
|
577 |
|
|
{
|
578 |
|
|
DEBUG(0, "cs: cb_release(bus %d)\n", s->cap.cb_dev->subordinate->number);
|
579 |
|
|
}
|
580 |
|
|
|
581 |
|
|
/*=====================================================================
|
582 |
|
|
|
583 |
|
|
cb_enable() has the job of configuring a socket for a Cardbus
|
584 |
|
|
card, and initializing the card's PCI configuration registers.
|
585 |
|
|
|
586 |
|
|
It first sets up the Cardbus bridge windows, for IO and memory
|
587 |
|
|
accesses. Then, it initializes each card function's base address
|
588 |
|
|
registers, interrupt line register, and command register.
|
589 |
|
|
|
590 |
|
|
It is called as part of the RequestConfiguration card service.
|
591 |
|
|
It should be called after a previous call to cb_config() (via the
|
592 |
|
|
RequestIO service).
|
593 |
|
|
|
594 |
|
|
======================================================================*/
|
595 |
|
|
|
596 |
|
|
void cb_enable(socket_info_t * s)
|
597 |
|
|
{
|
598 |
|
|
struct pci_dev *dev;
|
599 |
|
|
u_char i;
|
600 |
|
|
|
601 |
|
|
DEBUG(0, "cs: cb_enable(bus %d)\n", s->cap.cb_dev->subordinate->number);
|
602 |
|
|
|
603 |
|
|
/* Configure bridge */
|
604 |
|
|
cb_release_cis_mem(s);
|
605 |
|
|
|
606 |
|
|
/* Set up PCI interrupt and command registers */
|
607 |
|
|
for (i = 0; i < s->functions; i++) {
|
608 |
|
|
dev = &s->cb_config[i].dev;
|
609 |
|
|
pci_writeb(dev, PCI_COMMAND, PCI_COMMAND_MASTER |
|
610 |
|
|
PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
|
611 |
|
|
pci_writeb(dev, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES / 4);
|
612 |
|
|
}
|
613 |
|
|
|
614 |
|
|
if (s->irq.AssignedIRQ) {
|
615 |
|
|
for (i = 0; i < s->functions; i++) {
|
616 |
|
|
dev = &s->cb_config[i].dev;
|
617 |
|
|
pci_writeb(dev, PCI_INTERRUPT_LINE, s->irq.AssignedIRQ);
|
618 |
|
|
}
|
619 |
|
|
s->socket.io_irq = s->irq.AssignedIRQ;
|
620 |
|
|
s->ss_entry->set_socket(s->sock, &s->socket);
|
621 |
|
|
}
|
622 |
|
|
}
|
623 |
|
|
|
624 |
|
|
/*======================================================================
|
625 |
|
|
|
626 |
|
|
cb_disable() unconfigures a Cardbus card previously set up by
|
627 |
|
|
cb_enable().
|
628 |
|
|
|
629 |
|
|
It is called from the ReleaseConfiguration service.
|
630 |
|
|
|
631 |
|
|
======================================================================*/
|
632 |
|
|
|
633 |
|
|
void cb_disable(socket_info_t * s)
|
634 |
|
|
{
|
635 |
|
|
DEBUG(0, "cs: cb_disable(bus %d)\n", s->cap.cb_dev->subordinate->number);
|
636 |
|
|
|
637 |
|
|
/* Turn off bridge windows */
|
638 |
|
|
cb_release_cis_mem(s);
|
639 |
|
|
}
|