mirror of https://gitee.com/openkylin/linux.git
pcmcia: CardBus doesn't need CIS access
At least no in-kernel CardBus-capable PCI driver makes use of the CIS access functions. Therefore, it seems sensible to remove this unused code, and cleanup cardbus.c a lot. CC: Jesse Barnes <jbarnes@virtuousgeek.org> CC: Linus Torvalds <torvalds@linux-foundation.org> Tested-by: Wolfram Sang <w.sang@pengutronix.de> Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
This commit is contained in:
parent
88b060d6c0
commit
57197b9b77
|
@ -20,170 +20,12 @@
|
|||
*/
|
||||
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include <pcmcia/cs_types.h>
|
||||
#include <pcmcia/ss.h>
|
||||
#include <pcmcia/cs.h>
|
||||
#include <pcmcia/cistpl.h>
|
||||
#include "cs_internal.h"
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
/* Offsets in the Expansion ROM Image Header */
|
||||
#define ROM_SIGNATURE 0x0000 /* 2 bytes */
|
||||
#define ROM_DATA_PTR 0x0018 /* 2 bytes */
|
||||
|
||||
/* Offsets in the CardBus PC Card Data Structure */
|
||||
#define PCDATA_SIGNATURE 0x0000 /* 4 bytes */
|
||||
#define PCDATA_VPD_PTR 0x0008 /* 2 bytes */
|
||||
#define PCDATA_LENGTH 0x000a /* 2 bytes */
|
||||
#define PCDATA_REVISION 0x000c
|
||||
#define PCDATA_IMAGE_SZ 0x0010 /* 2 bytes */
|
||||
#define PCDATA_ROM_LEVEL 0x0012 /* 2 bytes */
|
||||
#define PCDATA_CODE_TYPE 0x0014
|
||||
#define PCDATA_INDICATOR 0x0015
|
||||
|
||||
/*=====================================================================
|
||||
|
||||
Expansion ROM's have a special layout, and pointers specify an
|
||||
image number and an offset within that image. xlate_rom_addr()
|
||||
converts an image/offset address to an absolute offset from the
|
||||
ROM's base address.
|
||||
|
||||
=====================================================================*/
|
||||
|
||||
static u_int xlate_rom_addr(void __iomem *b, u_int addr)
|
||||
{
|
||||
u_int img = 0, ofs = 0, sz;
|
||||
u_short data;
|
||||
while ((readb(b) == 0x55) && (readb(b + 1) == 0xaa)) {
|
||||
if (img == (addr >> 28))
|
||||
return (addr & 0x0fffffff) + ofs;
|
||||
data = readb(b + ROM_DATA_PTR) + (readb(b + ROM_DATA_PTR + 1) << 8);
|
||||
sz = 512 * (readb(b + data + PCDATA_IMAGE_SZ) +
|
||||
(readb(b + data + PCDATA_IMAGE_SZ + 1) << 8));
|
||||
if ((sz == 0) || (readb(b + data + PCDATA_INDICATOR) & 0x80))
|
||||
break;
|
||||
b += sz;
|
||||
ofs += sz;
|
||||
img++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*=====================================================================
|
||||
|
||||
These are similar to setup_cis_mem and release_cis_mem for 16-bit
|
||||
cards. The "result" that is used externally is the cb_cis_virt
|
||||
pointer in the struct pcmcia_socket structure.
|
||||
|
||||
=====================================================================*/
|
||||
|
||||
static void cb_release_cis_mem(struct pcmcia_socket *s)
|
||||
{
|
||||
if (s->cb_cis_virt) {
|
||||
dev_dbg(&s->dev, "cb_release_cis_mem()\n");
|
||||
iounmap(s->cb_cis_virt);
|
||||
s->cb_cis_virt = NULL;
|
||||
s->cb_cis_res = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int cb_setup_cis_mem(struct pcmcia_socket *s, struct resource *res)
|
||||
{
|
||||
unsigned int start, size;
|
||||
|
||||
if (res == s->cb_cis_res)
|
||||
return 0;
|
||||
|
||||
if (s->cb_cis_res)
|
||||
cb_release_cis_mem(s);
|
||||
|
||||
start = res->start;
|
||||
size = res->end - start + 1;
|
||||
s->cb_cis_virt = ioremap(start, size);
|
||||
|
||||
if (!s->cb_cis_virt)
|
||||
return -1;
|
||||
|
||||
s->cb_cis_res = res;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*=====================================================================
|
||||
|
||||
This is used by the CIS processing code to read CIS information
|
||||
from a CardBus device.
|
||||
|
||||
=====================================================================*/
|
||||
|
||||
int read_cb_mem(struct pcmcia_socket *s, int space, u_int addr, u_int len,
|
||||
void *ptr)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
struct resource *res;
|
||||
|
||||
dev_dbg(&s->dev, "read_cb_mem(%d, %#x, %u)\n", space, addr, len);
|
||||
|
||||
dev = pci_get_slot(s->cb_dev->subordinate, 0);
|
||||
if (!dev)
|
||||
goto fail;
|
||||
|
||||
/* Config space? */
|
||||
if (space == 0) {
|
||||
if (addr + len > 0x100)
|
||||
goto failput;
|
||||
for (; len; addr++, ptr++, len--)
|
||||
pci_read_config_byte(dev, addr, ptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
res = dev->resource + space - 1;
|
||||
|
||||
pci_dev_put(dev);
|
||||
|
||||
if (!res->flags)
|
||||
goto fail;
|
||||
|
||||
if (cb_setup_cis_mem(s, res) != 0)
|
||||
goto fail;
|
||||
|
||||
if (space == 7) {
|
||||
addr = xlate_rom_addr(s->cb_cis_virt, addr);
|
||||
if (addr == 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (addr + len > res->end - res->start)
|
||||
goto fail;
|
||||
|
||||
memcpy_fromio(ptr, s->cb_cis_virt + addr, len);
|
||||
return 0;
|
||||
|
||||
failput:
|
||||
pci_dev_put(dev);
|
||||
fail:
|
||||
memset(ptr, 0xff, len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*=====================================================================
|
||||
|
||||
cb_alloc() and cb_free() allocate and free the kernel data
|
||||
structures for a Cardbus device, and handle the lowest level PCI
|
||||
device setup issues.
|
||||
|
||||
=====================================================================*/
|
||||
|
||||
static void cardbus_config_irq_and_cls(struct pci_bus *bus, int irq)
|
||||
{
|
||||
|
@ -215,6 +57,13 @@ static void cardbus_config_irq_and_cls(struct pci_bus *bus, int irq)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* cb_alloc() - add CardBus device
|
||||
* @s: the pcmcia_socket where the CardBus device is located
|
||||
*
|
||||
* cb_alloc() allocates the kernel data structures for a Cardbus device
|
||||
* and handles the lowest level PCI device setup issues.
|
||||
*/
|
||||
int __ref cb_alloc(struct pcmcia_socket *s)
|
||||
{
|
||||
struct pci_bus *bus = s->cb_dev->subordinate;
|
||||
|
@ -249,12 +98,16 @@ int __ref cb_alloc(struct pcmcia_socket *s)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* cb_free() - remove CardBus device
|
||||
* @s: the pcmcia_socket where the CardBus device was located
|
||||
*
|
||||
* cb_free() handles the lowest level PCI device cleanup.
|
||||
*/
|
||||
void cb_free(struct pcmcia_socket *s)
|
||||
{
|
||||
struct pci_dev *bridge = s->cb_dev;
|
||||
|
||||
cb_release_cis_mem(s);
|
||||
|
||||
if (bridge)
|
||||
pci_remove_behind_bridge(bridge);
|
||||
}
|
||||
|
|
|
@ -268,29 +268,27 @@ EXPORT_SYMBOL(pcmcia_write_cis_mem);
|
|||
static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr,
|
||||
size_t len, void *ptr)
|
||||
{
|
||||
struct cis_cache_entry *cis;
|
||||
int ret;
|
||||
struct cis_cache_entry *cis;
|
||||
int ret;
|
||||
|
||||
if (s->fake_cis) {
|
||||
if (s->fake_cis_len >= addr+len)
|
||||
memcpy(ptr, s->fake_cis+addr, len);
|
||||
else
|
||||
memset(ptr, 0xff, len);
|
||||
return;
|
||||
}
|
||||
if (s->state & SOCKET_CARDBUS)
|
||||
return;
|
||||
|
||||
list_for_each_entry(cis, &s->cis_cache, node) {
|
||||
if (cis->addr == addr && cis->len == len && cis->attr == attr) {
|
||||
memcpy(ptr, cis->cache, len);
|
||||
return;
|
||||
if (s->fake_cis) {
|
||||
if (s->fake_cis_len >= addr+len)
|
||||
memcpy(ptr, s->fake_cis+addr, len);
|
||||
else
|
||||
memset(ptr, 0xff, len);
|
||||
return;
|
||||
}
|
||||
|
||||
list_for_each_entry(cis, &s->cis_cache, node) {
|
||||
if (cis->addr == addr && cis->len == len && cis->attr == attr) {
|
||||
memcpy(ptr, cis->cache, len);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CARDBUS
|
||||
if (s->state & SOCKET_CARDBUS)
|
||||
ret = read_cb_mem(s, attr, addr, len, ptr);
|
||||
else
|
||||
#endif
|
||||
ret = pcmcia_read_cis_mem(s, attr, addr, len, ptr);
|
||||
|
||||
if (ret == 0) {
|
||||
|
@ -351,6 +349,9 @@ int verify_cis_cache(struct pcmcia_socket *s)
|
|||
struct cis_cache_entry *cis;
|
||||
char *buf;
|
||||
|
||||
if (s->state & SOCKET_CARDBUS)
|
||||
return -EINVAL;
|
||||
|
||||
buf = kmalloc(256, GFP_KERNEL);
|
||||
if (buf == NULL) {
|
||||
dev_printk(KERN_WARNING, &s->dev,
|
||||
|
@ -362,12 +363,8 @@ int verify_cis_cache(struct pcmcia_socket *s)
|
|||
|
||||
if (len > 256)
|
||||
len = 256;
|
||||
#ifdef CONFIG_CARDBUS
|
||||
if (s->state & SOCKET_CARDBUS)
|
||||
read_cb_mem(s, cis->attr, cis->addr, len, buf);
|
||||
else
|
||||
#endif
|
||||
pcmcia_read_cis_mem(s, cis->attr, cis->addr, len, buf);
|
||||
|
||||
pcmcia_read_cis_mem(s, cis->attr, cis->addr, len, buf);
|
||||
|
||||
if (memcmp(buf, cis->cache, len) != 0) {
|
||||
kfree(buf);
|
||||
|
@ -427,25 +424,16 @@ int pccard_get_first_tuple(struct pcmcia_socket *s, unsigned int function, tuple
|
|||
{
|
||||
if (!s)
|
||||
return -EINVAL;
|
||||
if (!(s->state & SOCKET_PRESENT))
|
||||
|
||||
if (!(s->state & SOCKET_PRESENT) || (s->state & SOCKET_CARDBUS))
|
||||
return -ENODEV;
|
||||
tuple->TupleLink = tuple->Flags = 0;
|
||||
#ifdef CONFIG_CARDBUS
|
||||
if (s->state & SOCKET_CARDBUS) {
|
||||
struct pci_dev *dev = s->cb_dev;
|
||||
u_int ptr;
|
||||
pci_bus_read_config_dword(dev->subordinate, 0, PCI_CARDBUS_CIS, &ptr);
|
||||
tuple->CISOffset = ptr & ~7;
|
||||
SPACE(tuple->Flags) = (ptr & 7);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
/* Assume presence of a LONGLINK_C to address 0 */
|
||||
tuple->CISOffset = tuple->LinkOffset = 0;
|
||||
SPACE(tuple->Flags) = HAS_LINK(tuple->Flags) = 1;
|
||||
}
|
||||
if (!(s->state & SOCKET_CARDBUS) && (s->functions > 1) &&
|
||||
!(tuple->Attributes & TUPLE_RETURN_COMMON)) {
|
||||
|
||||
/* Assume presence of a LONGLINK_C to address 0 */
|
||||
tuple->CISOffset = tuple->LinkOffset = 0;
|
||||
SPACE(tuple->Flags) = HAS_LINK(tuple->Flags) = 1;
|
||||
|
||||
if ((s->functions > 1) && !(tuple->Attributes & TUPLE_RETURN_COMMON)) {
|
||||
cisdata_t req = tuple->DesiredTuple;
|
||||
tuple->DesiredTuple = CISTPL_LONGLINK_MFC;
|
||||
if (pccard_get_next_tuple(s, function, tuple) == 0) {
|
||||
|
@ -481,7 +469,7 @@ static int follow_link(struct pcmcia_socket *s, tuple_t *tuple)
|
|||
} else {
|
||||
return -1;
|
||||
}
|
||||
if (!(s->state & SOCKET_CARDBUS) && SPACE(tuple->Flags)) {
|
||||
if (SPACE(tuple->Flags)) {
|
||||
/* This is ugly, but a common CIS error is to code the long
|
||||
link offset incorrectly, so we check the right spot... */
|
||||
read_cis_cache(s, SPACE(tuple->Flags), ofs, 5, link);
|
||||
|
@ -507,7 +495,7 @@ int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int function, tuple_
|
|||
|
||||
if (!s)
|
||||
return -EINVAL;
|
||||
if (!(s->state & SOCKET_PRESENT))
|
||||
if (!(s->state & SOCKET_PRESENT) || (s->state & SOCKET_CARDBUS))
|
||||
return -ENODEV;
|
||||
|
||||
link[1] = tuple->TupleLink;
|
||||
|
@ -1192,119 +1180,6 @@ static int parse_cftable_entry(tuple_t *tuple,
|
|||
|
||||
/*====================================================================*/
|
||||
|
||||
#ifdef CONFIG_CARDBUS
|
||||
|
||||
static int parse_bar(tuple_t *tuple, cistpl_bar_t *bar)
|
||||
{
|
||||
u_char *p;
|
||||
if (tuple->TupleDataLen < 6)
|
||||
return -EINVAL;
|
||||
p = (u_char *)tuple->TupleData;
|
||||
bar->attr = *p;
|
||||
p += 2;
|
||||
bar->size = get_unaligned_le32(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_config_cb(tuple_t *tuple, cistpl_config_t *config)
|
||||
{
|
||||
u_char *p;
|
||||
|
||||
p = (u_char *)tuple->TupleData;
|
||||
if ((*p != 3) || (tuple->TupleDataLen < 6))
|
||||
return -EINVAL;
|
||||
config->last_idx = *(++p);
|
||||
p++;
|
||||
config->base = get_unaligned_le32(p);
|
||||
config->subtuples = tuple->TupleDataLen - 6;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_cftable_entry_cb(tuple_t *tuple,
|
||||
cistpl_cftable_entry_cb_t *entry)
|
||||
{
|
||||
u_char *p, *q, features;
|
||||
|
||||
p = tuple->TupleData;
|
||||
q = p + tuple->TupleDataLen;
|
||||
entry->index = *p & 0x3f;
|
||||
entry->flags = 0;
|
||||
if (*p & 0x40)
|
||||
entry->flags |= CISTPL_CFTABLE_DEFAULT;
|
||||
|
||||
/* Process optional features */
|
||||
if (++p == q)
|
||||
return -EINVAL;
|
||||
features = *p; p++;
|
||||
|
||||
/* Power options */
|
||||
if ((features & 3) > 0) {
|
||||
p = parse_power(p, q, &entry->vcc);
|
||||
if (p == NULL)
|
||||
return -EINVAL;
|
||||
} else
|
||||
entry->vcc.present = 0;
|
||||
if ((features & 3) > 1) {
|
||||
p = parse_power(p, q, &entry->vpp1);
|
||||
if (p == NULL)
|
||||
return -EINVAL;
|
||||
} else
|
||||
entry->vpp1.present = 0;
|
||||
if ((features & 3) > 2) {
|
||||
p = parse_power(p, q, &entry->vpp2);
|
||||
if (p == NULL)
|
||||
return -EINVAL;
|
||||
} else
|
||||
entry->vpp2.present = 0;
|
||||
|
||||
/* I/O window options */
|
||||
if (features & 0x08) {
|
||||
if (p == q)
|
||||
return -EINVAL;
|
||||
entry->io = *p; p++;
|
||||
} else
|
||||
entry->io = 0;
|
||||
|
||||
/* Interrupt options */
|
||||
if (features & 0x10) {
|
||||
p = parse_irq(p, q, &entry->irq);
|
||||
if (p == NULL)
|
||||
return -EINVAL;
|
||||
} else
|
||||
entry->irq.IRQInfo1 = 0;
|
||||
|
||||
if (features & 0x20) {
|
||||
if (p == q)
|
||||
return -EINVAL;
|
||||
entry->mem = *p; p++;
|
||||
} else
|
||||
entry->mem = 0;
|
||||
|
||||
/* Misc features */
|
||||
if (features & 0x80) {
|
||||
if (p == q)
|
||||
return -EINVAL;
|
||||
entry->flags |= (*p << 8);
|
||||
if (*p & 0x80) {
|
||||
if (++p == q)
|
||||
return -EINVAL;
|
||||
entry->flags |= (*p << 16);
|
||||
}
|
||||
while (*p & 0x80)
|
||||
if (++p == q)
|
||||
return -EINVAL;
|
||||
p++;
|
||||
}
|
||||
|
||||
entry->subtuples = q-p;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
static int parse_device_geo(tuple_t *tuple, cistpl_device_geo_t *geo)
|
||||
{
|
||||
u_char *p, *q;
|
||||
|
@ -1406,17 +1281,6 @@ int pcmcia_parse_tuple(tuple_t *tuple, cisparse_t *parse)
|
|||
case CISTPL_DEVICE_A:
|
||||
ret = parse_device(tuple, &parse->device);
|
||||
break;
|
||||
#ifdef CONFIG_CARDBUS
|
||||
case CISTPL_BAR:
|
||||
ret = parse_bar(tuple, &parse->bar);
|
||||
break;
|
||||
case CISTPL_CONFIG_CB:
|
||||
ret = parse_config_cb(tuple, &parse->config);
|
||||
break;
|
||||
case CISTPL_CFTABLE_ENTRY_CB:
|
||||
ret = parse_cftable_entry_cb(tuple, &parse->cftable_entry_cb);
|
||||
break;
|
||||
#endif
|
||||
case CISTPL_CHECKSUM:
|
||||
ret = parse_checksum(tuple, &parse->checksum);
|
||||
break;
|
||||
|
|
|
@ -244,12 +244,6 @@ struct pcmcia_socket {
|
|||
#endif /* CONFIG_PCMCIA_IOCTL */
|
||||
#endif /* CONFIG_PCMCIA */
|
||||
|
||||
/* cardbus (32-bit) */
|
||||
#ifdef CONFIG_CARDBUS
|
||||
struct resource *cb_cis_res;
|
||||
void __iomem *cb_cis_virt;
|
||||
#endif /* CONFIG_CARDBUS */
|
||||
|
||||
/* socket device */
|
||||
struct device dev;
|
||||
/* data internal to the socket driver */
|
||||
|
|
Loading…
Reference in New Issue