cardbus.c revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac
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#define IN_CARD_SERVICES 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <pcmcia/version.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <pcmcia/cs_types.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <pcmcia/ss.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <pcmcia/cs.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <pcmcia/bulkmem.h> 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <pcmcia/cistpl.h> 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "cs_internal.h" 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================*/ 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FIND_FIRST_BIT(n) ((n) - ((n) & ((n)-1))) 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Offsets in the Expansion ROM Image Header */ 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ROM_SIGNATURE 0x0000 /* 2 bytes */ 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ROM_DATA_PTR 0x0018 /* 2 bytes */ 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Offsets in the CardBus PC Card Data Structure */ 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PCDATA_SIGNATURE 0x0000 /* 4 bytes */ 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PCDATA_VPD_PTR 0x0008 /* 2 bytes */ 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PCDATA_LENGTH 0x000a /* 2 bytes */ 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PCDATA_REVISION 0x000c 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PCDATA_IMAGE_SZ 0x0010 /* 2 bytes */ 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PCDATA_ROM_LEVEL 0x0012 /* 2 bytes */ 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PCDATA_CODE_TYPE 0x0014 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PCDATA_INDICATOR 0x0015 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*===================================================================== 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Expansion ROM's have a special layout, and pointers specify an 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds image number and an offset within that image. xlate_rom_addr() 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds converts an image/offset address to an absolute offset from the 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ROM's base address. 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds=====================================================================*/ 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u_int xlate_rom_addr(void __iomem *b, u_int addr) 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int img = 0, ofs = 0, sz; 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_short data; 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while ((readb(b) == 0x55) && (readb(b + 1) == 0xaa)) { 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (img == (addr >> 28)) 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (addr & 0x0fffffff) + ofs; 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data = readb(b + ROM_DATA_PTR) + (readb(b + ROM_DATA_PTR + 1) << 8); 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sz = 512 * (readb(b + data + PCDATA_IMAGE_SZ) + 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (readb(b + data + PCDATA_IMAGE_SZ + 1) << 8)); 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((sz == 0) || (readb(b + data + PCDATA_INDICATOR) & 0x80)) 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds b += sz; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ofs += sz; 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds img++; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*===================================================================== 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds These are similar to setup_cis_mem and release_cis_mem for 16-bit 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cards. The "result" that is used externally is the cb_cis_virt 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pointer in the struct pcmcia_socket structure. 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds=====================================================================*/ 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void cb_release_cis_mem(struct pcmcia_socket * s) 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (s->cb_cis_virt) { 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs_dbg(s, 1, "cb_release_cis_mem()\n"); 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iounmap(s->cb_cis_virt); 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->cb_cis_virt = NULL; 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->cb_cis_res = NULL; 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int cb_setup_cis_mem(struct pcmcia_socket * s, struct resource *res) 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int start, size; 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (res == s->cb_cis_res) 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (s->cb_cis_res) 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb_release_cis_mem(s); 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds start = res->start; 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size = res->end - start + 1; 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->cb_cis_virt = ioremap(start, size); 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!s->cb_cis_virt) 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->cb_cis_res = res; 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*===================================================================== 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This is used by the CIS processing code to read CIS information 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds from a CardBus device. 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds=====================================================================*/ 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint read_cb_mem(struct pcmcia_socket * s, int space, u_int addr, u_int len, void *ptr) 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_dev *dev; 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct resource *res; 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs_dbg(s, 3, "read_cb_mem(%d, %#x, %u)\n", space, addr, len); 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev = pci_find_slot(s->cb_dev->subordinate->number, 0); 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev) 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Config space? */ 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (space == 0) { 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (addr + len > 0x100) 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (; len; addr++, ptr++, len--) 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_read_config_byte(dev, addr, ptr); 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res = dev->resource + space - 1; 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!res->flags) 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cb_setup_cis_mem(s, res) != 0) 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (space == 7) { 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr = xlate_rom_addr(s->cb_cis_virt, addr); 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (addr == 0) 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (addr + len > res->end - res->start) 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy_fromio(ptr, s->cb_cis_virt + addr, len); 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 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 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 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); 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_enable_bridges(bus); 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_bus_add_devices(bus); 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->irq.AssignedIRQ = s->pci_irq; 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return CS_SUCCESS; 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid cb_free(struct pcmcia_socket * s) 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_dev *bridge = s->cb_dev; 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cb_release_cis_mem(s); 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bridge) 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_remove_behind_bridge(bridge); 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 248