ds.c 31.8 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
2
3
4
5
6
7
8
9
10
11
12
/*
 * ds.c -- 16-bit PCMCIA core support
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * The initial developer of the original code is David A. Hinds
 * <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
 * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
 *
 * (C) 1999		David A. Hinds
13
 * (C) 2003 - 2006	Dominik Brodowski
Linus Torvalds's avatar
Linus Torvalds committed
14
15
 */

16
#include <linux/kernel.h>
Linus Torvalds's avatar
Linus Torvalds committed
17
18
19
20
21
22
#include <linux/module.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/list.h>
#include <linux/delay.h>
#include <linux/workqueue.h>
23
#include <linux/crc32.h>
24
#include <linux/firmware.h>
25
#include <linux/kref.h>
Linus Torvalds's avatar
Linus Torvalds committed
26
27
28
29
30
31
32
33
34

#define IN_CARD_SERVICES
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
#include <pcmcia/ss.h>

#include "cs_internal.h"
35
#include "ds_internal.h"
Linus Torvalds's avatar
Linus Torvalds committed
36
37
38
39
40
41
42
43
44
45

/*====================================================================*/

/* Module parameters */

MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
MODULE_DESCRIPTION("PCMCIA Driver Services");
MODULE_LICENSE("GPL");

#ifdef DEBUG
46
int ds_pc_debug;
Linus Torvalds's avatar
Linus Torvalds committed
47
48
49
50
51
52
53
54
55
56
57

module_param_named(pc_debug, ds_pc_debug, int, 0644);

#define ds_dbg(lvl, fmt, arg...) do {				\
	if (ds_pc_debug > (lvl))					\
		printk(KERN_DEBUG "ds: " fmt , ## arg);		\
} while (0)
#else
#define ds_dbg(lvl, fmt, arg...) do { } while (0)
#endif

58
spinlock_t pcmcia_dev_list_lock;
Linus Torvalds's avatar
Linus Torvalds committed
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158

/*====================================================================*/

/* code which was in cs.c before */

/* String tables for error messages */

typedef struct lookup_t {
    int key;
    char *msg;
} lookup_t;

static const lookup_t error_table[] = {
    { CS_SUCCESS,		"Operation succeeded" },
    { CS_BAD_ADAPTER,		"Bad adapter" },
    { CS_BAD_ATTRIBUTE, 	"Bad attribute", },
    { CS_BAD_BASE,		"Bad base address" },
    { CS_BAD_EDC,		"Bad EDC" },
    { CS_BAD_IRQ,		"Bad IRQ" },
    { CS_BAD_OFFSET,		"Bad offset" },
    { CS_BAD_PAGE,		"Bad page number" },
    { CS_READ_FAILURE,		"Read failure" },
    { CS_BAD_SIZE,		"Bad size" },
    { CS_BAD_SOCKET,		"Bad socket" },
    { CS_BAD_TYPE,		"Bad type" },
    { CS_BAD_VCC,		"Bad Vcc" },
    { CS_BAD_VPP,		"Bad Vpp" },
    { CS_BAD_WINDOW,		"Bad window" },
    { CS_WRITE_FAILURE,		"Write failure" },
    { CS_NO_CARD,		"No card present" },
    { CS_UNSUPPORTED_FUNCTION,	"Usupported function" },
    { CS_UNSUPPORTED_MODE,	"Unsupported mode" },
    { CS_BAD_SPEED,		"Bad speed" },
    { CS_BUSY,			"Resource busy" },
    { CS_GENERAL_FAILURE,	"General failure" },
    { CS_WRITE_PROTECTED,	"Write protected" },
    { CS_BAD_ARG_LENGTH,	"Bad argument length" },
    { CS_BAD_ARGS,		"Bad arguments" },
    { CS_CONFIGURATION_LOCKED,	"Configuration locked" },
    { CS_IN_USE,		"Resource in use" },
    { CS_NO_MORE_ITEMS,		"No more items" },
    { CS_OUT_OF_RESOURCE,	"Out of resource" },
    { CS_BAD_HANDLE,		"Bad handle" },
    { CS_BAD_TUPLE,		"Bad CIS tuple" }
};


static const lookup_t service_table[] = {
    { AccessConfigurationRegister,	"AccessConfigurationRegister" },
    { AddSocketServices,		"AddSocketServices" },
    { AdjustResourceInfo,		"AdjustResourceInfo" },
    { CheckEraseQueue,			"CheckEraseQueue" },
    { CloseMemory,			"CloseMemory" },
    { DeregisterClient,			"DeregisterClient" },
    { DeregisterEraseQueue,		"DeregisterEraseQueue" },
    { GetCardServicesInfo,		"GetCardServicesInfo" },
    { GetClientInfo,			"GetClientInfo" },
    { GetConfigurationInfo,		"GetConfigurationInfo" },
    { GetEventMask,			"GetEventMask" },
    { GetFirstClient,			"GetFirstClient" },
    { GetFirstRegion,			"GetFirstRegion" },
    { GetFirstTuple,			"GetFirstTuple" },
    { GetNextClient,			"GetNextClient" },
    { GetNextRegion,			"GetNextRegion" },
    { GetNextTuple,			"GetNextTuple" },
    { GetStatus,			"GetStatus" },
    { GetTupleData,			"GetTupleData" },
    { MapMemPage,			"MapMemPage" },
    { ModifyConfiguration,		"ModifyConfiguration" },
    { ModifyWindow,			"ModifyWindow" },
    { OpenMemory,			"OpenMemory" },
    { ParseTuple,			"ParseTuple" },
    { ReadMemory,			"ReadMemory" },
    { RegisterClient,			"RegisterClient" },
    { RegisterEraseQueue,		"RegisterEraseQueue" },
    { RegisterMTD,			"RegisterMTD" },
    { ReleaseConfiguration,		"ReleaseConfiguration" },
    { ReleaseIO,			"ReleaseIO" },
    { ReleaseIRQ,			"ReleaseIRQ" },
    { ReleaseWindow,			"ReleaseWindow" },
    { RequestConfiguration,		"RequestConfiguration" },
    { RequestIO,			"RequestIO" },
    { RequestIRQ,			"RequestIRQ" },
    { RequestSocketMask,		"RequestSocketMask" },
    { RequestWindow,			"RequestWindow" },
    { ResetCard,			"ResetCard" },
    { SetEventMask,			"SetEventMask" },
    { ValidateCIS,			"ValidateCIS" },
    { WriteMemory,			"WriteMemory" },
    { BindDevice,			"BindDevice" },
    { BindMTD,				"BindMTD" },
    { ReportError,			"ReportError" },
    { SuspendCard,			"SuspendCard" },
    { ResumeCard,			"ResumeCard" },
    { EjectCard,			"EjectCard" },
    { InsertCard,			"InsertCard" },
    { ReplaceCIS,			"ReplaceCIS" }
};


159
static int pcmcia_report_error(struct pcmcia_device *p_dev, error_info_t *err)
Linus Torvalds's avatar
Linus Torvalds committed
160
161
162
163
{
	int i;
	char *serv;

164
	if (!p_dev)
Linus Torvalds's avatar
Linus Torvalds committed
165
		printk(KERN_NOTICE);
166
	else
Linus Torvalds's avatar
Linus Torvalds committed
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
		printk(KERN_NOTICE "%s: ", p_dev->dev.bus_id);

	for (i = 0; i < ARRAY_SIZE(service_table); i++)
		if (service_table[i].key == err->func)
			break;
	if (i < ARRAY_SIZE(service_table))
		serv = service_table[i].msg;
	else
		serv = "Unknown service number";

	for (i = 0; i < ARRAY_SIZE(error_table); i++)
		if (error_table[i].key == err->retcode)
			break;
	if (i < ARRAY_SIZE(error_table))
		printk("%s: %s\n", serv, error_table[i].msg);
	else
		printk("%s: Unknown error code %#x\n", serv, err->retcode);

	return CS_SUCCESS;
} /* report_error */

/* end of code which was in cs.c before */

/*======================================================================*/

192
void cs_error(struct pcmcia_device *p_dev, int func, int ret)
Linus Torvalds's avatar
Linus Torvalds committed
193
194
{
	error_info_t err = { func, ret };
195
	pcmcia_report_error(p_dev, &err);
Linus Torvalds's avatar
Linus Torvalds committed
196
197
198
}
EXPORT_SYMBOL(cs_error);

199
200
201
202
203
204
205

static void pcmcia_check_driver(struct pcmcia_driver *p_drv)
{
	struct pcmcia_device_id *did = p_drv->id_table;
	unsigned int i;
	u32 hash;

206
	if (!p_drv->probe || !p_drv->remove)
Pavel Roskin's avatar
Pavel Roskin committed
207
208
		printk(KERN_DEBUG "pcmcia: %s lacks a requisite callback "
		       "function\n", p_drv->drv.name);
209

210
211
212
213
214
215
216
217
218
219
220
221
222
	while (did && did->match_flags) {
		for (i=0; i<4; i++) {
			if (!did->prod_id[i])
				continue;

			hash = crc32(0, did->prod_id[i], strlen(did->prod_id[i]));
			if (hash == did->prod_id_hash[i])
				continue;

			printk(KERN_DEBUG "pcmcia: %s: invalid hash for "
			       "product string \"%s\": is 0x%x, should "
			       "be 0x%x\n", p_drv->drv.name, did->prod_id[i],
			       did->prod_id_hash[i], hash);
223
224
225
			printk(KERN_DEBUG "pcmcia: see "
				"Documentation/pcmcia/devicetable.txt for "
				"details\n");
226
227
228
229
230
231
232
		}
		did++;
	}

	return;
}

233
234
235
236
237
238

#ifdef CONFIG_PCMCIA_LOAD_CIS

/**
 * pcmcia_load_firmware - load CIS from userspace if device-provided is broken
 * @dev - the pcmcia device which needs a CIS override
239
 * @filename - requested filename in /lib/firmware/
240
241
242
 *
 * This uses the in-kernel firmware loading mechanism to use a "fake CIS" if
 * the one provided by the card is broken. The firmware files reside in
243
 * /lib/firmware/ in userspace.
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
 */
static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
{
	struct pcmcia_socket *s = dev->socket;
	const struct firmware *fw;
	char path[20];
	int ret=-ENOMEM;
	cisdump_t *cis;

	if (!filename)
		return -EINVAL;

	ds_dbg(1, "trying to load firmware %s\n", filename);

	if (strlen(filename) > 14)
		return -EINVAL;

	snprintf(path, 20, "%s", filename);

	if (request_firmware(&fw, path, &dev->dev) == 0) {
		if (fw->size >= CISTPL_MAX_CIS_SIZE)
			goto release;

267
		cis = kzalloc(sizeof(cisdump_t), GFP_KERNEL);
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
		if (!cis)
			goto release;

		cis->Length = fw->size + 1;
		memcpy(cis->Data, fw->data, fw->size);

		if (!pcmcia_replace_cis(s, cis))
			ret = 0;
	}
 release:
	release_firmware(fw);

	return (ret);
}

#else /* !CONFIG_PCMCIA_LOAD_CIS */

static inline int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
{
	return -ENODEV;
}

#endif


Linus Torvalds's avatar
Linus Torvalds committed
293
294
295
296
297
298
299
300
301
302
303
304
305
/*======================================================================*/


/**
 * pcmcia_register_driver - register a PCMCIA driver with the bus core
 *
 * Registers a PCMCIA driver with the PCMCIA bus core.
 */
int pcmcia_register_driver(struct pcmcia_driver *driver)
{
	if (!driver)
		return -EINVAL;

306
307
	pcmcia_check_driver(driver);

Linus Torvalds's avatar
Linus Torvalds committed
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
	/* initialize common fields */
	driver->drv.bus = &pcmcia_bus_type;
	driver->drv.owner = driver->owner;

	return driver_register(&driver->drv);
}
EXPORT_SYMBOL(pcmcia_register_driver);

/**
 * pcmcia_unregister_driver - unregister a PCMCIA driver with the bus core
 */
void pcmcia_unregister_driver(struct pcmcia_driver *driver)
{
	driver_unregister(&driver->drv);
}
EXPORT_SYMBOL(pcmcia_unregister_driver);


/* pcmcia_device handling */

328
struct pcmcia_device * pcmcia_get_dev(struct pcmcia_device *p_dev)
Linus Torvalds's avatar
Linus Torvalds committed
329
330
331
332
333
334
335
336
{
	struct device *tmp_dev;
	tmp_dev = get_device(&p_dev->dev);
	if (!tmp_dev)
		return NULL;
	return to_pcmcia_dev(tmp_dev);
}

337
void pcmcia_put_dev(struct pcmcia_device *p_dev)
Linus Torvalds's avatar
Linus Torvalds committed
338
339
340
341
342
{
	if (p_dev)
		put_device(&p_dev->dev);
}

343
344
345
346
347
348
static void pcmcia_release_function(struct kref *ref)
{
	struct config_t *c = container_of(ref, struct config_t, ref);
	kfree(c);
}

Linus Torvalds's avatar
Linus Torvalds committed
349
350
351
352
static void pcmcia_release_dev(struct device *dev)
{
	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
	ds_dbg(1, "releasing dev %p\n", p_dev);
353
	pcmcia_put_socket(p_dev->socket);
354
	kfree(p_dev->devname);
355
	kref_put(&p_dev->function_config->ref, pcmcia_release_function);
Linus Torvalds's avatar
Linus Torvalds committed
356
357
358
	kfree(p_dev);
}

359
360
361
362
363
364
365
366
static void pcmcia_add_pseudo_device(struct pcmcia_socket *s)
{
	if (!s->pcmcia_state.device_add_pending) {
		s->pcmcia_state.device_add_pending = 1;
		schedule_work(&s->device_add);
	}
	return;
}
Linus Torvalds's avatar
Linus Torvalds committed
367
368
369
370
371

static int pcmcia_device_probe(struct device * dev)
{
	struct pcmcia_device *p_dev;
	struct pcmcia_driver *p_drv;
372
	struct pcmcia_device_id *did;
373
	struct pcmcia_socket *s;
Linus Torvalds's avatar
Linus Torvalds committed
374
375
376
377
378
379
380
381
	int ret = 0;

	dev = get_device(dev);
	if (!dev)
		return -ENODEV;

	p_dev = to_pcmcia_dev(dev);
	p_drv = to_pcmcia_drv(dev->driver);
382
	s = p_dev->socket;
Linus Torvalds's avatar
Linus Torvalds committed
383

384
385
	if ((!p_drv->probe) || (!p_dev->function_config) ||
	    (!try_module_get(p_drv->owner))) {
Linus Torvalds's avatar
Linus Torvalds committed
386
387
388
389
		ret = -EINVAL;
		goto put_dev;
	}

390
	ret = p_drv->probe(p_dev);
391
392
393
394
395
396
397
398
399
	if (ret)
		goto put_module;

	/* handle pseudo multifunction devices:
	 * there are at most two pseudo multifunction devices.
	 * if we're matching against the first, schedule a
	 * call which will then check whether there are two
	 * pseudo devices, and if not, add the second one.
	 */
400
	did = p_dev->dev.driver_data;
401
	if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) &&
402
403
	    (p_dev->socket->device_count == 1) && (p_dev->device_no == 0))
		pcmcia_add_pseudo_device(p_dev->socket);
404
405

 put_module:
Linus Torvalds's avatar
Linus Torvalds committed
406
407
408
	if (ret)
		module_put(p_drv->owner);
 put_dev:
409
	if (ret)
Linus Torvalds's avatar
Linus Torvalds committed
410
411
412
413
414
		put_device(dev);
	return (ret);
}


415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
/*
 * Removes a PCMCIA card from the device tree and socket list.
 */
static void pcmcia_card_remove(struct pcmcia_socket *s, struct pcmcia_device *leftover)
{
	struct pcmcia_device	*p_dev;
	struct pcmcia_device	*tmp;
	unsigned long		flags;

	ds_dbg(2, "unbind_request(%d)\n", s->sock);


	if (!leftover)
		s->device_count = 0;
	else
		s->device_count = 1;

	/* unregister all pcmcia_devices registered with this socket, except leftover */
	list_for_each_entry_safe(p_dev, tmp, &s->devices_list, socket_device_list) {
		if (p_dev == leftover)
			continue;

		spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
		list_del(&p_dev->socket_device_list);
		p_dev->_removed=1;
		spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);

		device_unregister(&p_dev->dev);
	}

	return;
}

Linus Torvalds's avatar
Linus Torvalds committed
448
449
450
451
static int pcmcia_device_remove(struct device * dev)
{
	struct pcmcia_device *p_dev;
	struct pcmcia_driver *p_drv;
452
	struct pcmcia_device_id *did;
453
	int i;
Linus Torvalds's avatar
Linus Torvalds committed
454
455
456

	p_dev = to_pcmcia_dev(dev);
	p_drv = to_pcmcia_drv(dev->driver);
457
458
459
460
461

	/* If we're removing the primary module driving a
	 * pseudo multi-function card, we need to unbind
	 * all devices
	 */
462
	did = p_dev->dev.driver_data;
463
	if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) &&
464
465
466
467
468
	    (p_dev->socket->device_count != 0) &&
	    (p_dev->device_no == 0))
		pcmcia_card_remove(p_dev->socket, p_dev);

	/* detach the "instance" */
469
470
	if (!p_drv)
		return 0;
Linus Torvalds's avatar
Linus Torvalds committed
471

472
	if (p_drv->remove)
473
474
	       	p_drv->remove(p_dev);

475
476
	p_dev->dev_node = NULL;

477
	/* check for proper unloading */
478
	if (p_dev->_irq || p_dev->_io || p_dev->_locked)
479
480
		printk(KERN_INFO "pcmcia: driver %s did not release config properly\n",
		       p_drv->drv.name);
481

482
	for (i = 0; i < MAX_WIN; i++)
483
		if (p_dev->_win & CLIENT_WIN_REQ(i))
484
485
			printk(KERN_INFO "pcmcia: driver %s did not release windows properly\n",
			       p_drv->drv.name);
486

487
488
489
	/* references from pcmcia_probe_device */
	pcmcia_put_dev(p_dev);
	module_put(p_drv->owner);
Linus Torvalds's avatar
Linus Torvalds committed
490
491
492
493
494
495
496
497
498
499
500
501

	return 0;
}


/*
 * pcmcia_device_query -- determine information about a pcmcia device
 */
static int pcmcia_device_query(struct pcmcia_device *p_dev)
{
	cistpl_manfid_t manf_id;
	cistpl_funcid_t func_id;
502
	cistpl_vers_1_t	*vers1;
Linus Torvalds's avatar
Linus Torvalds committed
503
504
	unsigned int i;

505
506
507
508
	vers1 = kmalloc(sizeof(*vers1), GFP_KERNEL);
	if (!vers1)
		return -ENOMEM;

Linus Torvalds's avatar
Linus Torvalds committed
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
	if (!pccard_read_tuple(p_dev->socket, p_dev->func,
			       CISTPL_MANFID, &manf_id)) {
		p_dev->manf_id = manf_id.manf;
		p_dev->card_id = manf_id.card;
		p_dev->has_manf_id = 1;
		p_dev->has_card_id = 1;
	}

	if (!pccard_read_tuple(p_dev->socket, p_dev->func,
			       CISTPL_FUNCID, &func_id)) {
		p_dev->func_id = func_id.func;
		p_dev->has_func_id = 1;
	} else {
		/* rule of thumb: cards with no FUNCID, but with
		 * common memory device geometry information, are
		 * probably memory cards (from pcmcia-cs) */
525
526
527
528
529
530
531
		cistpl_device_geo_t *devgeo;

		devgeo = kmalloc(sizeof(*devgeo), GFP_KERNEL);
		if (!devgeo) {
			kfree(vers1);
			return -ENOMEM;
		}
Linus Torvalds's avatar
Linus Torvalds committed
532
		if (!pccard_read_tuple(p_dev->socket, p_dev->func,
533
				      CISTPL_DEVICE_GEO, devgeo)) {
Linus Torvalds's avatar
Linus Torvalds committed
534
535
536
537
538
			ds_dbg(0, "mem device geometry probably means "
			       "FUNCID_MEMORY\n");
			p_dev->func_id = CISTPL_FUNCID_MEMORY;
			p_dev->has_func_id = 1;
		}
539
		kfree(devgeo);
Linus Torvalds's avatar
Linus Torvalds committed
540
541
542
	}

	if (!pccard_read_tuple(p_dev->socket, p_dev->func, CISTPL_VERS_1,
543
544
			       vers1)) {
		for (i=0; i < vers1->ns; i++) {
Linus Torvalds's avatar
Linus Torvalds committed
545
546
547
			char *tmp;
			unsigned int length;

548
			tmp = vers1->str + vers1->ofs[i];
Linus Torvalds's avatar
Linus Torvalds committed
549
550

			length = strlen(tmp) + 1;
551
			if ((length < 2) || (length > 255))
Linus Torvalds's avatar
Linus Torvalds committed
552
553
554
555
556
557
558
559
560
561
562
563
				continue;

			p_dev->prod_id[i] = kmalloc(sizeof(char) * length,
						    GFP_KERNEL);
			if (!p_dev->prod_id[i])
				continue;

			p_dev->prod_id[i] = strncpy(p_dev->prod_id[i],
						    tmp, length);
		}
	}

564
	kfree(vers1);
Linus Torvalds's avatar
Linus Torvalds committed
565
566
567
568
569
570
571
572
573
574
575
	return 0;
}


/* device_add_lock is needed to avoid double registration by cardmgr and kernel.
 * Serializes pcmcia_device_add; will most likely be removed in future.
 *
 * While it has the caveat that adding new PCMCIA devices inside(!) device_register()
 * won't work, this doesn't matter much at the moment: the driver core doesn't
 * support it either.
 */
576
static DEFINE_MUTEX(device_add_lock);
Linus Torvalds's avatar
Linus Torvalds committed
577

578
struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int function)
Linus Torvalds's avatar
Linus Torvalds committed
579
{
580
	struct pcmcia_device *p_dev, *tmp_dev;
Linus Torvalds's avatar
Linus Torvalds committed
581
	unsigned long flags;
582
	int bus_id_len;
Linus Torvalds's avatar
Linus Torvalds committed
583

584
	s = pcmcia_get_socket(s);
Linus Torvalds's avatar
Linus Torvalds committed
585
586
587
	if (!s)
		return NULL;

588
	mutex_lock(&device_add_lock);
Linus Torvalds's avatar
Linus Torvalds committed
589

590
591
592
593
	/* max of 2 devices per card */
	if (s->device_count == 2)
		goto err_put;

594
	p_dev = kzalloc(sizeof(struct pcmcia_device), GFP_KERNEL);
Linus Torvalds's avatar
Linus Torvalds committed
595
596
597
	if (!p_dev)
		goto err_put;

598
	p_dev->socket = s;
Linus Torvalds's avatar
Linus Torvalds committed
599
600
	p_dev->device_no = (s->device_count++);
	p_dev->func   = function;
601
602
	if (s->functions <= function)
		s->functions = function + 1;
Linus Torvalds's avatar
Linus Torvalds committed
603
604

	p_dev->dev.bus = &pcmcia_bus_type;
605
	p_dev->dev.parent = s->dev.dev;
Linus Torvalds's avatar
Linus Torvalds committed
606
	p_dev->dev.release = pcmcia_release_dev;
607
608
609
610
611
612
	bus_id_len = sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no);

	p_dev->devname = kmalloc(6 + bus_id_len + 1, GFP_KERNEL);
	if (!p_dev->devname)
		goto err_free;
	sprintf (p_dev->devname, "pcmcia%s", p_dev->dev.bus_id);
Linus Torvalds's avatar
Linus Torvalds committed
613
614
615

	/* compat */
	spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
616
617
618
619
620
621
622
623
624
625
626
627
628

	/*
	 * p_dev->function_config must be the same for all card functions.
	 * Note that this is serialized by the device_add_lock, so that
	 * only one such struct will be created.
	 */
        list_for_each_entry(tmp_dev, &s->devices_list, socket_device_list)
                if (p_dev->func == tmp_dev->func) {
			p_dev->function_config = tmp_dev->function_config;
			kref_get(&p_dev->function_config->ref);
		}

	/* Add to the list in pcmcia_bus_socket */
629
	list_add(&p_dev->socket_device_list, &s->devices_list);
630

Linus Torvalds's avatar
Linus Torvalds committed
631
632
	spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);

633
634
635
636
637
638
639
640
	if (!p_dev->function_config) {
		p_dev->function_config = kzalloc(sizeof(struct config_t),
						 GFP_KERNEL);
		if (!p_dev->function_config)
			goto err_unreg;
		kref_init(&p_dev->function_config->ref);
	}

641
642
643
	printk(KERN_NOTICE "pcmcia: registering new device %s\n",
	       p_dev->devname);

644
645
	pcmcia_device_query(p_dev);

646
647
	if (device_register(&p_dev->dev))
		goto err_unreg;
Linus Torvalds's avatar
Linus Torvalds committed
648

649
	mutex_unlock(&device_add_lock);
Linus Torvalds's avatar
Linus Torvalds committed
650
651
652

	return p_dev;

653
654
655
656
657
 err_unreg:
	spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
	list_del(&p_dev->socket_device_list);
	spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);

Linus Torvalds's avatar
Linus Torvalds committed
658
 err_free:
659
	kfree(p_dev->devname);
Linus Torvalds's avatar
Linus Torvalds committed
660
661
662
	kfree(p_dev);
	s->device_count--;
 err_put:
663
	mutex_unlock(&device_add_lock);
664
	pcmcia_put_socket(s);
Linus Torvalds's avatar
Linus Torvalds committed
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679

	return NULL;
}


static int pcmcia_card_add(struct pcmcia_socket *s)
{
	cisinfo_t cisinfo;
	cistpl_longlink_mfc_t mfc;
	unsigned int no_funcs, i;
	int ret = 0;

	if (!(s->resource_setup_done))
		return -EAGAIN; /* try again, but later... */

680
681
682
	if (pcmcia_validate_mem(s))
		return -EAGAIN; /* try again, but later... */

Linus Torvalds's avatar
Linus Torvalds committed
683
684
685
686
687
688
689
690
691
692
693
694
	ret = pccard_validate_cis(s, BIND_FN_ALL, &cisinfo);
	if (ret || !cisinfo.Chains) {
		ds_dbg(0, "invalid CIS or invalid resources\n");
		return -ENODEV;
	}

	if (!pccard_read_tuple(s, BIND_FN_ALL, CISTPL_LONGLINK_MFC, &mfc))
		no_funcs = mfc.nfn;
	else
		no_funcs = 1;

	for (i=0; i < no_funcs; i++)
695
		pcmcia_device_add(s, i);
Linus Torvalds's avatar
Linus Torvalds committed
696
697
698
699
700

	return (ret);
}


701
702
static void pcmcia_delayed_add_pseudo_device(void *data)
{
703
	struct pcmcia_socket *s = data;
704
	pcmcia_device_add(s, 0);
705
	s->pcmcia_state.device_add_pending = 0;
706
707
}

708
static int pcmcia_requery(struct device *dev, void * _data)
709
{
710
711
712
713
714
715
716
717
718
719
720
721
	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
	if (!p_dev->dev.driver)
		pcmcia_device_query(p_dev);

	return 0;
}

static void pcmcia_bus_rescan(struct pcmcia_socket *skt)
{
	int no_devices=0;
	unsigned long flags;

722
	/* must be called with skt_mutex held */
723
	spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
724
	if (list_empty(&skt->devices_list))
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
		no_devices=1;
	spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);

	/* if no devices were added for this socket yet because of
	 * missing resource information or other trouble, we need to
	 * do this now. */
	if (no_devices) {
		int ret = pcmcia_card_add(skt);
		if (ret)
			return;
	}

	/* some device information might have changed because of a CIS
	 * update or because we can finally read it correctly... so
	 * determine it again, overwriting old values if necessary. */
	bus_for_each_dev(&pcmcia_bus_type, NULL, NULL, pcmcia_requery);

	/* we re-scan all devices, not just the ones connected to this
	 * socket. This does not matter, though. */
744
	bus_rescan_devices(&pcmcia_bus_type);
745
}
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816

static inline int pcmcia_devmatch(struct pcmcia_device *dev,
				  struct pcmcia_device_id *did)
{
	if (did->match_flags & PCMCIA_DEV_ID_MATCH_MANF_ID) {
		if ((!dev->has_manf_id) || (dev->manf_id != did->manf_id))
			return 0;
	}

	if (did->match_flags & PCMCIA_DEV_ID_MATCH_CARD_ID) {
		if ((!dev->has_card_id) || (dev->card_id != did->card_id))
			return 0;
	}

	if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNCTION) {
		if (dev->func != did->function)
			return 0;
	}

	if (did->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID1) {
		if (!dev->prod_id[0])
			return 0;
		if (strcmp(did->prod_id[0], dev->prod_id[0]))
			return 0;
	}

	if (did->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID2) {
		if (!dev->prod_id[1])
			return 0;
		if (strcmp(did->prod_id[1], dev->prod_id[1]))
			return 0;
	}

	if (did->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID3) {
		if (!dev->prod_id[2])
			return 0;
		if (strcmp(did->prod_id[2], dev->prod_id[2]))
			return 0;
	}

	if (did->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID4) {
		if (!dev->prod_id[3])
			return 0;
		if (strcmp(did->prod_id[3], dev->prod_id[3]))
			return 0;
	}

	if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) {
		if (dev->device_no != did->device_no)
			return 0;
	}

	if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID) {
		if ((!dev->has_func_id) || (dev->func_id != did->func_id))
			return 0;

		/* if this is a pseudo-multi-function device,
		 * we need explicit matches */
		if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO)
			return 0;
		if (dev->device_no)
			return 0;

		/* also, FUNC_ID matching needs to be activated by userspace
		 * after it has re-checked that there is no possible module
		 * with a prod_id/manf_id/card_id match.
		 */
		if (!dev->allow_func_id_match)
			return 0;
	}

817
	if (did->match_flags & PCMCIA_DEV_ID_MATCH_FAKE_CIS) {
818
819
820
821
		if (!dev->socket->fake_cis)
			pcmcia_load_firmware(dev, did->cisfile);

		if (!dev->socket->fake_cis)
822
823
824
			return 0;
	}

825
826
827
828
829
830
831
832
833
	if (did->match_flags & PCMCIA_DEV_ID_MATCH_ANONYMOUS) {
		int i;
		for (i=0; i<4; i++)
			if (dev->prod_id[i])
				return 0;
		if (dev->has_manf_id || dev->has_card_id || dev->has_func_id)
			return 0;
	}

834
835
836
837
838
839
	dev->dev.driver_data = (void *) did;

	return 1;
}


Linus Torvalds's avatar
Linus Torvalds committed
840
841
842
static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) {
	struct pcmcia_device * p_dev = to_pcmcia_dev(dev);
	struct pcmcia_driver * p_drv = to_pcmcia_drv(drv);
843
	struct pcmcia_device_id *did = p_drv->id_table;
Linus Torvalds's avatar
Linus Torvalds committed
844

845
#ifdef CONFIG_PCMCIA_IOCTL
Linus Torvalds's avatar
Linus Torvalds committed
846
847
848
	/* matching by cardmgr */
	if (p_dev->cardmgr == p_drv)
		return 1;
849
#endif
Linus Torvalds's avatar
Linus Torvalds committed
850

851
852
853
854
855
856
	while (did && did->match_flags) {
		if (pcmcia_devmatch(p_dev, did))
			return 1;
		did++;
	}

Linus Torvalds's avatar
Linus Torvalds committed
857
858
859
	return 0;
}

860
861
#ifdef CONFIG_HOTPLUG

862
863
static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp,
			     char *buffer, int buffer_size)
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
{
	struct pcmcia_device *p_dev;
	int i, length = 0;
	u32 hash[4] = { 0, 0, 0, 0};

	if (!dev)
		return -ENODEV;

	p_dev = to_pcmcia_dev(dev);

	/* calculate hashes */
	for (i=0; i<4; i++) {
		if (!p_dev->prod_id[i])
			continue;
		hash[i] = crc32(0, p_dev->prod_id[i], strlen(p_dev->prod_id[i]));
	}

	i = 0;

883
884
885
886
	if (add_uevent_var(envp, num_envp, &i,
			   buffer, buffer_size, &length,
			   "SOCKET_NO=%u",
			   p_dev->socket->sock))
887
888
		return -ENOMEM;

889
890
891
892
	if (add_uevent_var(envp, num_envp, &i,
			   buffer, buffer_size, &length,
			   "DEVICE_NO=%02X",
			   p_dev->device_no))
893
894
		return -ENOMEM;

895
896
897
898
899
900
901
902
903
904
905
906
907
	if (add_uevent_var(envp, num_envp, &i,
			   buffer, buffer_size, &length,
			   "MODALIAS=pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X"
			   "pa%08Xpb%08Xpc%08Xpd%08X",
			   p_dev->has_manf_id ? p_dev->manf_id : 0,
			   p_dev->has_card_id ? p_dev->card_id : 0,
			   p_dev->has_func_id ? p_dev->func_id : 0,
			   p_dev->func,
			   p_dev->device_no,
			   hash[0],
			   hash[1],
			   hash[2],
			   hash[3]))
908
909
910
911
912
913
914
915
916
		return -ENOMEM;

	envp[i] = NULL;

	return 0;
}

#else

917
static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp,
918
919
920
921
922
923
924
			      char *buffer, int buffer_size)
{
	return -ENODEV;
}

#endif

Linus Torvalds's avatar
Linus Torvalds committed
925
926
927
/************************ per-device sysfs output ***************************/

#define pcmcia_device_attr(field, test, format)				\
928
static ssize_t field##_show (struct device *dev, struct device_attribute *attr, char *buf)		\
Linus Torvalds's avatar
Linus Torvalds committed
929
930
931
932
933
934
{									\
	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);		\
	return p_dev->test ? sprintf (buf, format, p_dev->field) : -ENODEV; \
}

#define pcmcia_device_stringattr(name, field)					\
935
static ssize_t name##_show (struct device *dev, struct device_attribute *attr, char *buf)		\
Linus Torvalds's avatar
Linus Torvalds committed
936
937
938
939
940
941
942
943
944
945
946
947
948
949
{									\
	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);		\
	return p_dev->field ? sprintf (buf, "%s\n", p_dev->field) : -ENODEV; \
}

pcmcia_device_attr(func, socket, "0x%02x\n");
pcmcia_device_attr(func_id, has_func_id, "0x%02x\n");
pcmcia_device_attr(manf_id, has_manf_id, "0x%04x\n");
pcmcia_device_attr(card_id, has_card_id, "0x%04x\n");
pcmcia_device_stringattr(prod_id1, prod_id[0]);
pcmcia_device_stringattr(prod_id2, prod_id[1]);
pcmcia_device_stringattr(prod_id3, prod_id[2]);
pcmcia_device_stringattr(prod_id4, prod_id[3]);

950
951
952
953
954

static ssize_t pcmcia_show_pm_state(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);

955
	if (p_dev->suspended)
956
957
958
959
960
961
962
963
964
965
966
967
968
969
		return sprintf(buf, "off\n");
	else
		return sprintf(buf, "on\n");
}

static ssize_t pcmcia_store_pm_state(struct device *dev, struct device_attribute *attr,
				     const char *buf, size_t count)
{
	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
	int ret = 0;

        if (!count)
                return -EINVAL;

970
	if ((!p_dev->suspended) && !strncmp(buf, "off", 3))
971
		ret = dpm_runtime_suspend(dev, PMSG_SUSPEND);
972
	else if (p_dev->suspended && !strncmp(buf, "on", 2))
973
974
975
976
977
978
		dpm_runtime_resume(dev);

	return ret ? ret : count;
}


979
static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
{
	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
	int i;
	u32 hash[4] = { 0, 0, 0, 0};

	/* calculate hashes */
	for (i=0; i<4; i++) {
		if (!p_dev->prod_id[i])
			continue;
		hash[i] = crc32(0,p_dev->prod_id[i],strlen(p_dev->prod_id[i]));
	}
	return sprintf(buf, "pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X"
				"pa%08Xpb%08Xpc%08Xpd%08X\n",
				p_dev->has_manf_id ? p_dev->manf_id : 0,
				p_dev->has_card_id ? p_dev->card_id : 0,
				p_dev->has_func_id ? p_dev->func_id : 0,
				p_dev->func, p_dev->device_no,
				hash[0], hash[1], hash[2], hash[3]);
}
999

1000
static ssize_t pcmcia_store_allow_func_id_match(struct device *dev,
For faster browsing, not all history is shown. View entire blame