#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/notifier.h>
+#include <linux/device.h>
#include <linux/init.h>
#include <asm/dma.h>
#include <asm/pgalloc.h>
#include <asm/mmu_context.h>
#include <asm/mach/irq.h>
+#include <asm/tlbflush.h>
#ifndef CONFIG_ARCH_RPC
#define HAVE_EXPMASK
asmlinkage extern int
ecard_loader_read(int off, volatile unsigned char *pa, loader_t loader);
+static const struct ecard_id *
+ecard_match_device(const struct ecard_id *ids, struct expansion_card *ec);
static inline unsigned short
ecard_getu16(unsigned char *v)
*ecp = ec;
slot_to_expcard[slot] = ec;
+
+ snprintf(ec->dev.bus_id, sizeof(ec->dev.bus_id), "ecard%d", slot);
+ strcpy(ec->dev.name, "fixme!");
+ ec->dev.parent = NULL;
+ ec->dev.bus = &ecard_bus_type;
+
+ device_register(&ec->dev);
+
return 0;
nodev:
if (finding_pos->claimed)
continue;
+ if (finding_pos->dev.driver)
+ continue;
+
if (!cids) {
if ((finding_pos->cid.id ^ cid) == 0)
break;
} else {
- unsigned int manufacturer, product;
- int i;
-
- manufacturer = finding_pos->cid.manufacturer;
- product = finding_pos->cid.product;
-
- for (i = 0; cids[i].manufacturer != 65535; i++)
- if (manufacturer == cids[i].manufacturer &&
- product == cids[i].product)
- break;
+ const struct ecard_id *id;
- if (cids[i].manufacturer != 65535)
+ id = ecard_match_device(cids, finding_pos);
+ if (id)
break;
}
}
* Locate all hardware - interrupt management and
* actual cards.
*/
-void __init ecard_init(void)
+static int __init ecard_init(void)
{
int slot, irqhw;
irqhw ? ecard_irqexp_handler : ecard_irq_handler);
ecard_proc_init();
+
+ return 0;
}
subsys_initcall(ecard_init);
+/*
+ * ECARD "bus"
+ */
+static const struct ecard_id *
+ecard_match_device(const struct ecard_id *ids, struct expansion_card *ec)
+{
+ int i;
+
+ for (i = 0; ids[i].manufacturer != 65535; i++)
+ if (ec->cid.manufacturer == ids[i].manufacturer &&
+ ec->cid.product == ids[i].product)
+ return ids + i;
+
+ return NULL;
+}
+
+static int ecard_drv_probe(struct device *dev)
+{
+ struct expansion_card *ec = ECARD_DEV(dev);
+ struct ecard_driver *drv = ECARD_DRV(dev->driver);
+ const struct ecard_id *id;
+
+ id = ecard_match_device(drv->id_table, ec);
+
+ return drv->probe(ec, id);
+}
+
+static int ecard_drv_remove(struct device *dev)
+{
+ struct expansion_card *ec = ECARD_DEV(dev);
+ struct ecard_driver *drv = ECARD_DRV(dev->driver);
+
+ drv->remove(ec);
+
+ return 0;
+}
+
+int ecard_register_driver(struct ecard_driver *drv)
+{
+ drv->drv.bus = &ecard_bus_type;
+ drv->drv.probe = ecard_drv_probe;
+ drv->drv.remove = ecard_drv_remove;
+
+ return driver_register(&drv->drv);
+}
+
+void ecard_remove_driver(struct ecard_driver *drv)
+{
+ remove_driver(&drv->drv);
+}
+
+static int ecard_match(struct device *_dev, struct device_driver *_drv)
+{
+ struct expansion_card *ec = ECARD_DEV(_dev);
+ struct ecard_driver *drv = ECARD_DRV(_drv);
+ int ret;
+
+ if (drv->id_table) {
+ ret = ecard_match_device(drv->id_table, ec) != NULL;
+ } else {
+ ret = ec->cid.id == drv->id;
+ }
+
+ return ret;
+}
+
+struct bus_type ecard_bus_type = {
+ .name = "ecard",
+ .match = ecard_match,
+};
+
+static int ecard_bus_init(void)
+{
+ return bus_register(&ecard_bus_type);
+}
+
+postcore_initcall(ecard_bus_init);
+
EXPORT_SYMBOL(ecard_startfind);
EXPORT_SYMBOL(ecard_find);
EXPORT_SYMBOL(ecard_readchunk);
EXPORT_SYMBOL(ecard_address);
+
+EXPORT_SYMBOL(ecard_register_driver);
+EXPORT_SYMBOL(ecard_remove_driver);
+
+EXPORT_SYMBOL(ecard_bus_type);
ECARD_SYNC = 3
} card_speed_t;
-typedef struct { /* Card ID structure */
- unsigned short manufacturer;
- unsigned short product;
+typedef struct ecard_id { /* Card ID structure */
+ unsigned short manufacturer;
+ unsigned short product;
+ void *data;
} card_ids;
struct in_ecid { /* Packed card ID information */
struct expansion_card {
struct expansion_card *next;
+ struct device dev;
+
/* Public data */
volatile unsigned char *irqaddr; /* address of IRQ register */
volatile unsigned char *fiqaddr; /* address of FIQ register */
#endif
+extern struct bus_type ecard_bus_type;
+
+#define ECARD_DEV(_d) container_of((_d), struct expansion_card, dev)
+
+struct ecard_driver {
+ int (*probe)(struct expansion_card *, const struct ecard_id *id);
+ void (*remove)(struct expansion_card *);
+ const struct ecard_id *id_table;
+ unsigned int id;
+ struct device_driver drv;
+};
+
+#define ECARD_DRV(_d) container_of((_d), struct ecard_driver, drv)
+
+#define ecard_set_drvdata(ec,data) dev_set_drvdata(&(ec)->dev, (data))
+#define ecard_get_drvdata(ec) dev_get_drvdata(&(ec)->dev)
+
+int ecard_register_driver(struct ecard_driver *);
+void ecard_remove_driver(struct ecard_driver *);
+
#endif