[PATCH 12/14] pcmcia: request CIS via firmware interface
Dominik Brodowski
linux at dominikbrodowski.net
Sun Feb 27 05:11:50 EST 2005
Use the firmware method to load replacement CIS tables. It is recommended
that the /lib/firmware/cis/ points to /etc/pcmcia/cis or the other way round
so that both old-style cardmgr and new-style hotplug/firmware can access
these "overwrite" files
Signed-off-by: Dominik Brodowski <linux at dominikbrodowski.net>
Index: 2.6.11-rc5/drivers/pcmcia/ds.c
===================================================================
--- 2.6.11-rc5.orig/drivers/pcmcia/ds.c 2005-02-27 08:42:43.000000000 +0100
+++ 2.6.11-rc5/drivers/pcmcia/ds.c 2005-02-27 08:51:28.000000000 +0100
@@ -36,6 +36,7 @@
#include <linux/kref.h>
#include <linux/workqueue.h>
#include <linux/crc32.h>
+#include <linux/firmware.h>
#include <asm/atomic.h>
@@ -295,6 +296,47 @@
}
#endif
+
+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, "cis/%s", filename);
+
+ if(request_firmware(&fw, path, &dev->dev) == 0) {
+ if (fw->size >= CISTPL_MAX_CIS_SIZE)
+ goto release;
+
+ cis = kmalloc(sizeof(cisdump_t), GFP_KERNEL);
+ if (!cis)
+ goto release;
+
+ memset(cis, 0, sizeof(cisdump_t));
+
+ 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);
+}
+
/*======================================================================*/
static struct pcmcia_driver * get_pcmcia_driver (dev_info_t *dev_info);
@@ -739,11 +781,11 @@
}
if (did->match_flags & PCMCIA_DEV_ID_MATCH_FAKE_CIS) {
- if (!dev->socket->fake_cis) {
- /* FIXME: evaluate using firmware helpers to
- * automagically load it from userspace */
+ if (!dev->socket->fake_cis)
+ pcmcia_load_firmware(dev, did->cisfile);
+
+ if (!dev->socket->fake_cis)
return 0;
- }
}
if (did->match_flags & PCMCIA_DEV_ID_MATCH_ANONYMUS) {
More information about the linux-pcmcia
mailing list