aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pcmcia/cardbus.c175
-rw-r--r--drivers/pcmcia/cistpl.c200
-rw-r--r--include/pcmcia/ss.h6
3 files changed, 46 insertions, 335 deletions
diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c
index d99f846451a3..ac0686efbf75 100644
--- a/drivers/pcmcia/cardbus.c
+++ b/drivers/pcmcia/cardbus.c
@@ -20,170 +20,12 @@
20 */ 20 */
21 21
22 22
23#include <linux/module.h>
24#include <linux/kernel.h> 23#include <linux/kernel.h>
25#include <linux/string.h> 24#include <linux/module.h>
26#include <linux/slab.h>
27#include <linux/mm.h>
28#include <linux/pci.h> 25#include <linux/pci.h>
29#include <linux/ioport.h>
30#include <linux/io.h>
31#include <asm/irq.h>
32 26
33#include <pcmcia/cs_types.h>
34#include <pcmcia/ss.h> 27#include <pcmcia/ss.h>
35#include <pcmcia/cs.h>
36#include <pcmcia/cistpl.h>
37#include "cs_internal.h"
38
39/*====================================================================*/
40
41/* Offsets in the Expansion ROM Image Header */
42#define ROM_SIGNATURE 0x0000 /* 2 bytes */
43#define ROM_DATA_PTR 0x0018 /* 2 bytes */
44
45/* Offsets in the CardBus PC Card Data Structure */
46#define PCDATA_SIGNATURE 0x0000 /* 4 bytes */
47#define PCDATA_VPD_PTR 0x0008 /* 2 bytes */
48#define PCDATA_LENGTH 0x000a /* 2 bytes */
49#define PCDATA_REVISION 0x000c
50#define PCDATA_IMAGE_SZ 0x0010 /* 2 bytes */
51#define PCDATA_ROM_LEVEL 0x0012 /* 2 bytes */
52#define PCDATA_CODE_TYPE 0x0014
53#define PCDATA_INDICATOR 0x0015
54
55/*=====================================================================
56
57 Expansion ROM's have a special layout, and pointers specify an
58 image number and an offset within that image. xlate_rom_addr()
59 converts an image/offset address to an absolute offset from the
60 ROM's base address.
61
62=====================================================================*/
63
64static u_int xlate_rom_addr(void __iomem *b, u_int addr)
65{
66 u_int img = 0, ofs = 0, sz;
67 u_short data;
68 while ((readb(b) == 0x55) && (readb(b + 1) == 0xaa)) {
69 if (img == (addr >> 28))
70 return (addr & 0x0fffffff) + ofs;
71 data = readb(b + ROM_DATA_PTR) + (readb(b + ROM_DATA_PTR + 1) << 8);
72 sz = 512 * (readb(b + data + PCDATA_IMAGE_SZ) +
73 (readb(b + data + PCDATA_IMAGE_SZ + 1) << 8));
74 if ((sz == 0) || (readb(b + data + PCDATA_INDICATOR) & 0x80))
75 break;
76 b += sz;
77 ofs += sz;
78 img++;
79 }
80 return 0;
81}
82
83/*=====================================================================
84
85 These are similar to setup_cis_mem and release_cis_mem for 16-bit
86 cards. The "result" that is used externally is the cb_cis_virt
87 pointer in the struct pcmcia_socket structure.
88
89=====================================================================*/
90
91static void cb_release_cis_mem(struct pcmcia_socket *s)
92{
93 if (s->cb_cis_virt) {
94 dev_dbg(&s->dev, "cb_release_cis_mem()\n");
95 iounmap(s->cb_cis_virt);
96 s->cb_cis_virt = NULL;
97 s->cb_cis_res = NULL;
98 }
99}
100
101static int cb_setup_cis_mem(struct pcmcia_socket *s, struct resource *res)
102{
103 unsigned int start, size;
104
105 if (res == s->cb_cis_res)
106 return 0;
107
108 if (s->cb_cis_res)
109 cb_release_cis_mem(s);
110
111 start = res->start;
112 size = res->end - start + 1;
113 s->cb_cis_virt = ioremap(start, size);
114
115 if (!s->cb_cis_virt)
116 return -1;
117
118 s->cb_cis_res = res;
119
120 return 0;
121}
122
123/*=====================================================================
124
125 This is used by the CIS processing code to read CIS information
126 from a CardBus device.
127
128=====================================================================*/
129
130int read_cb_mem(struct pcmcia_socket *s, int space, u_int addr, u_int len,
131 void *ptr)
132{
133 struct pci_dev *dev;
134 struct resource *res;
135
136 dev_dbg(&s->dev, "read_cb_mem(%d, %#x, %u)\n", space, addr, len);
137 28
138 dev = pci_get_slot(s->cb_dev->subordinate, 0);
139 if (!dev)
140 goto fail;
141
142 /* Config space? */
143 if (space == 0) {
144 if (addr + len > 0x100)
145 goto failput;
146 for (; len; addr++, ptr++, len--)
147 pci_read_config_byte(dev, addr, ptr);
148 return 0;
149 }
150
151 res = dev->resource + space - 1;
152
153 pci_dev_put(dev);
154
155 if (!res->flags)
156 goto fail;
157
158 if (cb_setup_cis_mem(s, res) != 0)
159 goto fail;
160
161 if (space == 7) {
162 addr = xlate_rom_addr(s->cb_cis_virt, addr);
163 if (addr == 0)
164 goto fail;
165 }
166
167 if (addr + len > res->end - res->start)
168 goto fail;
169
170 memcpy_fromio(ptr, s->cb_cis_virt + addr, len);
171 return 0;
172
173failput:
174 pci_dev_put(dev);
175fail:
176 memset(ptr, 0xff, len);
177 return -1;
178}
179
180/*=====================================================================
181
182 cb_alloc() and cb_free() allocate and free the kernel data
183 structures for a Cardbus device, and handle the lowest level PCI
184 device setup issues.
185
186=====================================================================*/
187 29
188static void cardbus_config_irq_and_cls(struct pci_bus *bus, int irq) 30static void cardbus_config_irq_and_cls(struct pci_bus *bus, int irq)
189{ 31{
@@ -215,6 +57,13 @@ static void cardbus_config_irq_and_cls(struct pci_bus *bus, int irq)
215 } 57 }
216} 58}
217 59
60/**
61 * cb_alloc() - add CardBus device
62 * @s: the pcmcia_socket where the CardBus device is located
63 *
64 * cb_alloc() allocates the kernel data structures for a Cardbus device
65 * and handles the lowest level PCI device setup issues.
66 */
218int __ref cb_alloc(struct pcmcia_socket *s) 67int __ref cb_alloc(struct pcmcia_socket *s)
219{ 68{
220 struct pci_bus *bus = s->cb_dev->subordinate; 69 struct pci_bus *bus = s->cb_dev->subordinate;
@@ -249,12 +98,16 @@ int __ref cb_alloc(struct pcmcia_socket *s)
249 return 0; 98 return 0;
250} 99}
251 100
101/**
102 * cb_free() - remove CardBus device
103 * @s: the pcmcia_socket where the CardBus device was located
104 *
105 * cb_free() handles the lowest level PCI device cleanup.
106 */
252void cb_free(struct pcmcia_socket *s) 107void cb_free(struct pcmcia_socket *s)
253{ 108{
254 struct pci_dev *bridge = s->cb_dev; 109 struct pci_dev *bridge = s->cb_dev;
255 110
256 cb_release_cis_mem(s);
257
258 if (bridge) 111 if (bridge)
259 pci_remove_behind_bridge(bridge); 112 pci_remove_behind_bridge(bridge);
260} 113}
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index a8323cb2e34d..368367ced62b 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -268,29 +268,27 @@ EXPORT_SYMBOL(pcmcia_write_cis_mem);
268static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, 268static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr,
269 size_t len, void *ptr) 269 size_t len, void *ptr)
270{ 270{
271 struct cis_cache_entry *cis; 271 struct cis_cache_entry *cis;
272 int ret; 272 int ret;
273 273
274 if (s->fake_cis) { 274 if (s->state & SOCKET_CARDBUS)
275 if (s->fake_cis_len >= addr+len) 275 return;
276 memcpy(ptr, s->fake_cis+addr, len);
277 else
278 memset(ptr, 0xff, len);
279 return;
280 }
281 276
282 list_for_each_entry(cis, &s->cis_cache, node) { 277 if (s->fake_cis) {
283 if (cis->addr == addr && cis->len == len && cis->attr == attr) { 278 if (s->fake_cis_len >= addr+len)
284 memcpy(ptr, cis->cache, len); 279 memcpy(ptr, s->fake_cis+addr, len);
285 return; 280 else
281 memset(ptr, 0xff, len);
282 return;
283 }
284
285 list_for_each_entry(cis, &s->cis_cache, node) {
286 if (cis->addr == addr && cis->len == len && cis->attr == attr) {
287 memcpy(ptr, cis->cache, len);
288 return;
289 }
286 } 290 }
287 }
288 291
289#ifdef CONFIG_CARDBUS
290 if (s->state & SOCKET_CARDBUS)
291 ret = read_cb_mem(s, attr, addr, len, ptr);
292 else
293#endif
294 ret = pcmcia_read_cis_mem(s, attr, addr, len, ptr); 292 ret = pcmcia_read_cis_mem(s, attr, addr, len, ptr);
295 293
296 if (ret == 0) { 294 if (ret == 0) {
@@ -351,6 +349,9 @@ int verify_cis_cache(struct pcmcia_socket *s)
351 struct cis_cache_entry *cis; 349 struct cis_cache_entry *cis;
352 char *buf; 350 char *buf;
353 351
352 if (s->state & SOCKET_CARDBUS)
353 return -EINVAL;
354
354 buf = kmalloc(256, GFP_KERNEL); 355 buf = kmalloc(256, GFP_KERNEL);
355 if (buf == NULL) { 356 if (buf == NULL) {
356 dev_printk(KERN_WARNING, &s->dev, 357 dev_printk(KERN_WARNING, &s->dev,
@@ -362,12 +363,8 @@ int verify_cis_cache(struct pcmcia_socket *s)
362 363
363 if (len > 256) 364 if (len > 256)
364 len = 256; 365 len = 256;
365#ifdef CONFIG_CARDBUS 366
366 if (s->state & SOCKET_CARDBUS) 367 pcmcia_read_cis_mem(s, cis->attr, cis->addr, len, buf);
367 read_cb_mem(s, cis->attr, cis->addr, len, buf);
368 else
369#endif
370 pcmcia_read_cis_mem(s, cis->attr, cis->addr, len, buf);
371 368
372 if (memcmp(buf, cis->cache, len) != 0) { 369 if (memcmp(buf, cis->cache, len) != 0) {
373 kfree(buf); 370 kfree(buf);
@@ -427,25 +424,16 @@ int pccard_get_first_tuple(struct pcmcia_socket *s, unsigned int function, tuple
427{ 424{
428 if (!s) 425 if (!s)
429 return -EINVAL; 426 return -EINVAL;
430 if (!(s->state & SOCKET_PRESENT)) 427
428 if (!(s->state & SOCKET_PRESENT) || (s->state & SOCKET_CARDBUS))
431 return -ENODEV; 429 return -ENODEV;
432 tuple->TupleLink = tuple->Flags = 0; 430 tuple->TupleLink = tuple->Flags = 0;
433#ifdef CONFIG_CARDBUS 431
434 if (s->state & SOCKET_CARDBUS) { 432 /* Assume presence of a LONGLINK_C to address 0 */
435 struct pci_dev *dev = s->cb_dev; 433 tuple->CISOffset = tuple->LinkOffset = 0;
436 u_int ptr; 434 SPACE(tuple->Flags) = HAS_LINK(tuple->Flags) = 1;
437 pci_bus_read_config_dword(dev->subordinate, 0, PCI_CARDBUS_CIS, &ptr); 435
438 tuple->CISOffset = ptr & ~7; 436 if ((s->functions > 1) && !(tuple->Attributes & TUPLE_RETURN_COMMON)) {
439 SPACE(tuple->Flags) = (ptr & 7);
440 } else
441#endif
442 {
443 /* Assume presence of a LONGLINK_C to address 0 */
444 tuple->CISOffset = tuple->LinkOffset = 0;
445 SPACE(tuple->Flags) = HAS_LINK(tuple->Flags) = 1;
446 }
447 if (!(s->state & SOCKET_CARDBUS) && (s->functions > 1) &&
448 !(tuple->Attributes & TUPLE_RETURN_COMMON)) {
449 cisdata_t req = tuple->DesiredTuple; 437 cisdata_t req = tuple->DesiredTuple;
450 tuple->DesiredTuple = CISTPL_LONGLINK_MFC; 438 tuple->DesiredTuple = CISTPL_LONGLINK_MFC;
451 if (pccard_get_next_tuple(s, function, tuple) == 0) { 439 if (pccard_get_next_tuple(s, function, tuple) == 0) {
@@ -481,7 +469,7 @@ static int follow_link(struct pcmcia_socket *s, tuple_t *tuple)
481 } else { 469 } else {
482 return -1; 470 return -1;
483 } 471 }
484 if (!(s->state & SOCKET_CARDBUS) && SPACE(tuple->Flags)) { 472 if (SPACE(tuple->Flags)) {
485 /* This is ugly, but a common CIS error is to code the long 473 /* This is ugly, but a common CIS error is to code the long
486 link offset incorrectly, so we check the right spot... */ 474 link offset incorrectly, so we check the right spot... */
487 read_cis_cache(s, SPACE(tuple->Flags), ofs, 5, link); 475 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_
507 495
508 if (!s) 496 if (!s)
509 return -EINVAL; 497 return -EINVAL;
510 if (!(s->state & SOCKET_PRESENT)) 498 if (!(s->state & SOCKET_PRESENT) || (s->state & SOCKET_CARDBUS))
511 return -ENODEV; 499 return -ENODEV;
512 500
513 link[1] = tuple->TupleLink; 501 link[1] = tuple->TupleLink;
@@ -1192,119 +1180,6 @@ static int parse_cftable_entry(tuple_t *tuple,
1192 1180
1193/*====================================================================*/ 1181/*====================================================================*/
1194 1182
1195#ifdef CONFIG_CARDBUS
1196
1197static int parse_bar(tuple_t *tuple, cistpl_bar_t *bar)
1198{
1199 u_char *p;
1200 if (tuple->TupleDataLen < 6)
1201 return -EINVAL;
1202 p = (u_char *)tuple->TupleData;
1203 bar->attr = *p;
1204 p += 2;
1205 bar->size = get_unaligned_le32(p);
1206 return 0;
1207}
1208
1209static int parse_config_cb(tuple_t *tuple, cistpl_config_t *config)
1210{
1211 u_char *p;
1212
1213 p = (u_char *)tuple->TupleData;
1214 if ((*p != 3) || (tuple->TupleDataLen < 6))
1215 return -EINVAL;
1216 config->last_idx = *(++p);
1217 p++;
1218 config->base = get_unaligned_le32(p);
1219 config->subtuples = tuple->TupleDataLen - 6;
1220 return 0;
1221}
1222
1223static int parse_cftable_entry_cb(tuple_t *tuple,
1224 cistpl_cftable_entry_cb_t *entry)
1225{
1226 u_char *p, *q, features;
1227
1228 p = tuple->TupleData;
1229 q = p + tuple->TupleDataLen;
1230 entry->index = *p & 0x3f;
1231 entry->flags = 0;
1232 if (*p & 0x40)
1233 entry->flags |= CISTPL_CFTABLE_DEFAULT;
1234
1235 /* Process optional features */
1236 if (++p == q)
1237 return -EINVAL;
1238 features = *p; p++;
1239
1240 /* Power options */
1241 if ((features & 3) > 0) {
1242 p = parse_power(p, q, &entry->vcc);
1243 if (p == NULL)
1244 return -EINVAL;
1245 } else
1246 entry->vcc.present = 0;
1247 if ((features & 3) > 1) {
1248 p = parse_power(p, q, &entry->vpp1);
1249 if (p == NULL)
1250 return -EINVAL;
1251 } else
1252 entry->vpp1.present = 0;
1253 if ((features & 3) > 2) {
1254 p = parse_power(p, q, &entry->vpp2);
1255 if (p == NULL)
1256 return -EINVAL;
1257 } else
1258 entry->vpp2.present = 0;
1259
1260 /* I/O window options */
1261 if (features & 0x08) {
1262 if (p == q)
1263 return -EINVAL;
1264 entry->io = *p; p++;
1265 } else
1266 entry->io = 0;
1267
1268 /* Interrupt options */
1269 if (features & 0x10) {
1270 p = parse_irq(p, q, &entry->irq);
1271 if (p == NULL)
1272 return -EINVAL;
1273 } else
1274 entry->irq.IRQInfo1 = 0;
1275
1276 if (features & 0x20) {
1277 if (p == q)
1278 return -EINVAL;
1279 entry->mem = *p; p++;
1280 } else
1281 entry->mem = 0;
1282
1283 /* Misc features */
1284 if (features & 0x80) {
1285 if (p == q)
1286 return -EINVAL;
1287 entry->flags |= (*p << 8);
1288 if (*p & 0x80) {
1289 if (++p == q)
1290 return -EINVAL;
1291 entry->flags |= (*p << 16);
1292 }
1293 while (*p & 0x80)
1294 if (++p == q)
1295 return -EINVAL;
1296 p++;
1297 }
1298
1299 entry->subtuples = q-p;
1300
1301 return 0;
1302}
1303
1304#endif
1305
1306/*====================================================================*/
1307
1308static int parse_device_geo(tuple_t *tuple, cistpl_device_geo_t *geo) 1183static int parse_device_geo(tuple_t *tuple, cistpl_device_geo_t *geo)
1309{ 1184{
1310 u_char *p, *q; 1185 u_char *p, *q;
@@ -1406,17 +1281,6 @@ int pcmcia_parse_tuple(tuple_t *tuple, cisparse_t *parse)
1406 case CISTPL_DEVICE_A: 1281 case CISTPL_DEVICE_A:
1407 ret = parse_device(tuple, &parse->device); 1282 ret = parse_device(tuple, &parse->device);
1408 break; 1283 break;
1409#ifdef CONFIG_CARDBUS
1410 case CISTPL_BAR:
1411 ret = parse_bar(tuple, &parse->bar);
1412 break;
1413 case CISTPL_CONFIG_CB:
1414 ret = parse_config_cb(tuple, &parse->config);
1415 break;
1416 case CISTPL_CFTABLE_ENTRY_CB:
1417 ret = parse_cftable_entry_cb(tuple, &parse->cftable_entry_cb);
1418 break;
1419#endif
1420 case CISTPL_CHECKSUM: 1284 case CISTPL_CHECKSUM:
1421 ret = parse_checksum(tuple, &parse->checksum); 1285 ret = parse_checksum(tuple, &parse->checksum);
1422 break; 1286 break;
diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h
index b0ebd11130cc..b4e5cfd49ce1 100644
--- a/include/pcmcia/ss.h
+++ b/include/pcmcia/ss.h
@@ -244,12 +244,6 @@ struct pcmcia_socket {
244#endif /* CONFIG_PCMCIA_IOCTL */ 244#endif /* CONFIG_PCMCIA_IOCTL */
245#endif /* CONFIG_PCMCIA */ 245#endif /* CONFIG_PCMCIA */
246 246
247 /* cardbus (32-bit) */
248#ifdef CONFIG_CARDBUS
249 struct resource *cb_cis_res;
250 void __iomem *cb_cis_virt;
251#endif /* CONFIG_CARDBUS */
252
253 /* socket device */ 247 /* socket device */
254 struct device dev; 248 struct device dev;
255 /* data internal to the socket driver */ 249 /* data internal to the socket driver */