cardbus.c revision 4c89e88bfde6a3c179790e21004f24e09a058290
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cardbus.c -- 16-bit PCMCIA core support
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License version 2 as
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * published by the Free Software Foundation.
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The initial developer of the original code is David A. Hinds
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (C) 1999		David A. Hinds
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Cardbus handling has been re-written to be more of a PCI bridge thing,
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and the PCI code basically does all the resource handling.
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		Linus, Jan 2000
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h>
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h>
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h>
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h>
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h>
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/irq.h>
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <pcmcia/cs_types.h>
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <pcmcia/ss.h>
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <pcmcia/cs.h>
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <pcmcia/cistpl.h>
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "cs_internal.h"
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================*/
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Offsets in the Expansion ROM Image Header */
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ROM_SIGNATURE		0x0000	/* 2 bytes */
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ROM_DATA_PTR		0x0018	/* 2 bytes */
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Offsets in the CardBus PC Card Data Structure */
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PCDATA_SIGNATURE	0x0000	/* 4 bytes */
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PCDATA_VPD_PTR		0x0008	/* 2 bytes */
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PCDATA_LENGTH		0x000a	/* 2 bytes */
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PCDATA_REVISION		0x000c
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PCDATA_IMAGE_SZ		0x0010	/* 2 bytes */
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PCDATA_ROM_LEVEL	0x0012	/* 2 bytes */
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PCDATA_CODE_TYPE	0x0014
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PCDATA_INDICATOR	0x0015
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*=====================================================================
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    Expansion ROM's have a special layout, and pointers specify an
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    image number and an offset within that image.  xlate_rom_addr()
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    converts an image/offset address to an absolute offset from the
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    ROM's base address.
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds=====================================================================*/
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u_int xlate_rom_addr(void __iomem *b, u_int addr)
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_int img = 0, ofs = 0, sz;
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_short data;
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while ((readb(b) == 0x55) && (readb(b + 1) == 0xaa)) {
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (img == (addr >> 28))
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (addr & 0x0fffffff) + ofs;
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data = readb(b + ROM_DATA_PTR) + (readb(b + ROM_DATA_PTR + 1) << 8);
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sz = 512 * (readb(b + data + PCDATA_IMAGE_SZ) +
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    (readb(b + data + PCDATA_IMAGE_SZ + 1) << 8));
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((sz == 0) || (readb(b + data + PCDATA_INDICATOR) & 0x80))
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		b += sz;
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ofs += sz;
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		img++;
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*=====================================================================
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    These are similar to setup_cis_mem and release_cis_mem for 16-bit
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    cards.  The "result" that is used externally is the cb_cis_virt
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    pointer in the struct pcmcia_socket structure.
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds=====================================================================*/
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void cb_release_cis_mem(struct pcmcia_socket * s)
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (s->cb_cis_virt) {
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cs_dbg(s, 1, "cb_release_cis_mem()\n");
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iounmap(s->cb_cis_virt);
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s->cb_cis_virt = NULL;
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s->cb_cis_res = NULL;
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int cb_setup_cis_mem(struct pcmcia_socket * s, struct resource *res)
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int start, size;
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (res == s->cb_cis_res)
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (s->cb_cis_res)
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cb_release_cis_mem(s);
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	start = res->start;
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	size = res->end - start + 1;
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	s->cb_cis_virt = ioremap(start, size);
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!s->cb_cis_virt)
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	s->cb_cis_res = res;
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*=====================================================================
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    This is used by the CIS processing code to read CIS information
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    from a CardBus device.
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds=====================================================================*/
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint read_cb_mem(struct pcmcia_socket * s, int space, u_int addr, u_int len, void *ptr)
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *dev;
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct resource *res;
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs_dbg(s, 3, "read_cb_mem(%d, %#x, %u)\n", space, addr, len);
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13774ae3221818eaf3884ceac931ba3cd2c00045483Alan Cox	dev = pci_get_slot(s->cb_dev->subordinate, 0);
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev)
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto fail;
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Config space? */
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (space == 0) {
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (addr + len > 0x100)
1441523508d6321436b6edfcd99aab04a344f9aed3fJulia Lawall			goto failput;
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (; len; addr++, ptr++, len--)
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_read_config_byte(dev, addr, ptr);
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	res = dev->resource + space - 1;
15174ae3221818eaf3884ceac931ba3cd2c00045483Alan Cox
15274ae3221818eaf3884ceac931ba3cd2c00045483Alan Cox	pci_dev_put(dev);
15374ae3221818eaf3884ceac931ba3cd2c00045483Alan Cox
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!res->flags)
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto fail;
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cb_setup_cis_mem(s, res) != 0)
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto fail;
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (space == 7) {
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		addr = xlate_rom_addr(s->cb_cis_virt, addr);
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (addr == 0)
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto fail;
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (addr + len > res->end - res->start)
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto fail;
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy_fromio(ptr, s->cb_cis_virt + addr, len);
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1721523508d6321436b6edfcd99aab04a344f9aed3fJulia Lawallfailput:
1731523508d6321436b6edfcd99aab04a344f9aed3fJulia Lawall	pci_dev_put(dev);
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfail:
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(ptr, 0xff, len);
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -1;
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*=====================================================================
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    cb_alloc() and cb_free() allocate and free the kernel data
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    structures for a Cardbus device, and handle the lowest level PCI
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    device setup issues.
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds=====================================================================*/
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Since there is only one interrupt available to CardBus
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * devices, all devices downstream of this device must
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * be using this IRQ.
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void cardbus_assign_irqs(struct pci_bus *bus, int irq)
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *dev;
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each_entry(dev, &bus->devices, bus_list) {
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u8 irq_pin;
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq_pin);
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (irq_pin) {
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dev->irq = irq;
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (dev->subordinate)
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cardbus_assign_irqs(dev->subordinate, irq);
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
210e772d782a6b0f14d491a95445f0ec6767d66fb29Sam Ravnborgint __ref cb_alloc(struct pcmcia_socket * s)
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_bus *bus = s->cb_dev->subordinate;
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *dev;
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int max, pass;
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0));
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds//	pcibios_fixup_bus(bus);
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	max = bus->secondary;
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (pass = 0; pass < 2; pass++)
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		list_for_each_entry(dev, &bus->devices, bus_list)
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				max = pci_scan_bridge(bus, dev, max, pass);
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Size all resources below the CardBus controller.
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_bus_size_bridges(bus);
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_bus_assign_resources(bus);
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cardbus_assign_irqs(bus, s->pci_irq);
2328c3520d4eb3b1bbf2e45fbae8dcfb8db06d5e775Daniel Ritz
2338c3520d4eb3b1bbf2e45fbae8dcfb8db06d5e775Daniel Ritz	/* socket specific tune function */
2348c3520d4eb3b1bbf2e45fbae8dcfb8db06d5e775Daniel Ritz	if (s->tune_bridge)
2358c3520d4eb3b1bbf2e45fbae8dcfb8db06d5e775Daniel Ritz		s->tune_bridge(s, bus);
2368c3520d4eb3b1bbf2e45fbae8dcfb8db06d5e775Daniel Ritz
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_enable_bridges(bus);
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_bus_add_devices(bus);
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	s->irq.AssignedIRQ = s->pci_irq;
2414c89e88bfde6a3c179790e21004f24e09a058290Dominik Brodowski	return 0;
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid cb_free(struct pcmcia_socket * s)
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *bridge = s->cb_dev;
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cb_release_cis_mem(s);
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (bridge)
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_remove_behind_bridge(bridge);
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
253