};
asmlinkage extern int
-ecard_loader_reset(volatile unsigned char *pa, loader_t loader);
+ecard_loader_reset(unsigned long base, loader_t loader);
asmlinkage extern int
-ecard_loader_read(int off, volatile unsigned char *pa, loader_t loader);
+ecard_loader_read(int off, unsigned long base, 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)
+static inline unsigned short ecard_getu16(unsigned char *v)
{
return v[0] | v[1] << 8;
}
-static inline signed long
-ecard_gets24(unsigned char *v)
+static inline signed long ecard_gets24(unsigned char *v)
{
return v[0] | v[1] << 8 | v[2] << 16 | ((v[2] & 0x80) ? 0xff000000 : 0);
}
-static inline ecard_t *
-slot_to_ecard(unsigned int slot)
+static inline ecard_t *slot_to_ecard(unsigned int slot)
{
return slot < MAX_ECARDS ? slot_to_expcard[slot] : NULL;
}
* From a security standpoint, we trust the card vendors. This
* may be a misplaced trust.
*/
-#define BUS_ADDR(x) ((((unsigned long)(x)) << 2) + IO_BASE)
-#define POD_INT_ADDR(x) ((volatile unsigned char *)\
- ((BUS_ADDR((x)) - IO_BASE) + IO_START))
-
static void ecard_task_reset(struct ecard_request *req)
{
struct expansion_card *ec = req->ec;
- if (ec->loader)
- ecard_loader_reset(POD_INT_ADDR(ec->podaddr), ec->loader);
+ struct resource *res;
+
+ res = ec->slot_no == 8
+ ? &ec->resource[ECARD_RES_MEMC]
+ : ec->type == ECARD_EASI
+ ? &ec->resource[ECARD_RES_EASI]
+ : &ec->resource[ECARD_RES_IOCSYNC];
+
+ ecard_loader_reset(res->start, ec->loader);
}
static void ecard_task_readbytes(struct ecard_request *req)
{
- unsigned char *buf = (unsigned char *)req->buffer;
- volatile unsigned char *base_addr =
- (volatile unsigned char *)POD_INT_ADDR(req->ec->podaddr);
+ struct expansion_card *ec = req->ec;
+ unsigned char *buf = req->buffer;
unsigned int len = req->length;
unsigned int off = req->address;
- if (req->ec->slot_no == 8) {
+ if (ec->slot_no == 8) {
+ void __iomem *base = (void __iomem *)
+ ec->resource[ECARD_RES_MEMC].start;
+
/*
* The card maintains an index which increments the address
* into a 4096-byte page on each access. We need to keep
* greater than the offset, reset the hardware index counter.
*/
if (off == 0 || index > off) {
- *base_addr = 0;
+ writeb(0, base);
index = 0;
}
* required offset. The read bytes are discarded.
*/
while (index < off) {
- unsigned char byte;
- byte = base_addr[page];
+ readb(base + page);
index += 1;
}
while (len--) {
- *buf++ = base_addr[page];
+ *buf++ = readb(base + page);
index += 1;
}
} else {
+ unsigned long base = (ec->type == ECARD_EASI
+ ? &ec->resource[ECARD_RES_EASI]
+ : &ec->resource[ECARD_RES_IOCSYNC])->start;
+ void __iomem *pbase = (void __iomem *)base;
- if (!req->use_loader || !req->ec->loader) {
+ if (!req->use_loader || !ec->loader) {
off *= 4;
while (len--) {
- *buf++ = base_addr[off];
+ *buf++ = readb(pbase + off);
off += 4;
}
} else {
* expansion card loader programs.
*/
*(unsigned long *)0x108 = 0;
- *buf++ = ecard_loader_read(off++, base_addr,
- req->ec->loader);
+ *buf++ = ecard_loader_read(off++, base,
+ ec->loader);
}
}
}
*/
pgd_t *src_pgd, *dst_pgd;
- src_pgd = pgd_offset(mm, IO_BASE);
+ src_pgd = pgd_offset(mm, (unsigned long)IO_BASE);
dst_pgd = pgd_offset(mm, IO_START);
memcpy(dst_pgd, src_pgd, sizeof(pgd_t) * (IO_SIZE / PGDIR_SIZE));
static int ecard_def_irq_pending(ecard_t *ec)
{
- return !ec->irqmask || ec->irqaddr[0] & ec->irqmask;
+ return !ec->irqmask || readb(ec->irqaddr) & ec->irqmask;
}
static void ecard_def_fiq_enable(ecard_t *ec, int fiqnr)
static int ecard_def_fiq_pending(ecard_t *ec)
{
- return !ec->fiqmask || ec->fiqaddr[0] & ec->fiqmask;
+ return !ec->fiqmask || readb(ec->fiqaddr) & ec->fiqmask;
}
static expansioncard_ops_t ecard_default_ops = {
ec->ops->irqpending(ec) ? "" : "not ");
else
printk("irqaddr %p, mask = %02X, status = %02X\n",
- ec->irqaddr, ec->irqmask, *ec->irqaddr);
+ ec->irqaddr, ec->irqmask, readb(ec->irqaddr));
}
}
#define IO_EC_MEMC8_BASE 0
#endif
-unsigned int ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed)
+unsigned int __ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed)
{
unsigned long address = 0;
int slot = ec->slot_no;
get_ecard_dev_info);
}
-#define ec_set_resource(ec,nr,st,sz,flg) \
+#define ec_set_resource(ec,nr,st,sz) \
do { \
(ec)->resource[nr].name = ec->dev.bus_id; \
(ec)->resource[nr].start = st; \
(ec)->resource[nr].end = (st) + (sz) - 1; \
- (ec)->resource[nr].flags = flg; \
+ (ec)->resource[nr].flags = IORESOURCE_MEM; \
} while (0)
-static void __init ecard_init_resources(struct expansion_card *ec)
+static void __init ecard_free_card(struct expansion_card *ec)
+{
+ int i;
+
+ for (i = 0; i < ECARD_NUM_RESOURCES; i++)
+ if (ec->resource[i].flags)
+ release_resource(&ec->resource[i]);
+
+ kfree(ec);
+}
+
+static struct expansion_card *__init ecard_alloc_card(int type, int slot)
{
- unsigned long base = PODSLOT_IOC4_BASE;
- unsigned int slot = ec->slot_no;
+ struct expansion_card *ec;
+ unsigned long base;
int i;
+ ec = kmalloc(sizeof(ecard_t), GFP_KERNEL);
+ if (!ec) {
+ ec = ERR_PTR(-ENOMEM);
+ goto nomem;
+ }
+
+ memset(ec, 0, sizeof(ecard_t));
+
+ ec->slot_no = slot;
+ ec->type = type;
+ ec->irq = NO_IRQ;
+ ec->fiq = NO_IRQ;
+ ec->dma = NO_DMA;
+ ec->ops = &ecard_default_ops;
+
+ snprintf(ec->dev.bus_id, sizeof(ec->dev.bus_id), "ecard%d", slot);
+ ec->dev.parent = NULL;
+ ec->dev.bus = &ecard_bus_type;
+ ec->dev.dma_mask = &ec->dma_mask;
+ ec->dma_mask = (u64)0xffffffff;
+
if (slot < 4) {
ec_set_resource(ec, ECARD_RES_MEMC,
PODSLOT_MEMC_BASE + (slot << 14),
- PODSLOT_MEMC_SIZE, IORESOURCE_MEM);
- base = PODSLOT_IOC0_BASE;
- }
+ PODSLOT_MEMC_SIZE);
+ base = PODSLOT_IOC0_BASE + (slot << 14);
+ } else
+ base = PODSLOT_IOC4_BASE + ((slot - 4) << 14);
#ifdef CONFIG_ARCH_RPC
if (slot < 8) {
ec_set_resource(ec, ECARD_RES_EASI,
PODSLOT_EASI_BASE + (slot << 24),
- PODSLOT_EASI_SIZE, IORESOURCE_MEM);
+ PODSLOT_EASI_SIZE);
}
if (slot == 8) {
- ec_set_resource(ec, ECARD_RES_MEMC, NETSLOT_BASE,
- NETSLOT_SIZE, IORESOURCE_MEM);
+ ec_set_resource(ec, ECARD_RES_MEMC, NETSLOT_BASE, NETSLOT_SIZE);
} else
#endif
- for (i = 0; i <= ECARD_RES_IOCSYNC - ECARD_RES_IOCSLOW; i++) {
+ for (i = 0; i <= ECARD_RES_IOCSYNC - ECARD_RES_IOCSLOW; i++)
ec_set_resource(ec, i + ECARD_RES_IOCSLOW,
- base + (slot << 14) + (i << 19),
- PODSLOT_IOC_SIZE, IORESOURCE_MEM);
- }
+ base + (i << 19), PODSLOT_IOC_SIZE);
for (i = 0; i < ECARD_NUM_RESOURCES; i++) {
- if (ec->resource[i].start &&
+ if (ec->resource[i].flags &&
request_resource(&iomem_resource, &ec->resource[i])) {
printk(KERN_ERR "%s: resource(s) not available\n",
ec->dev.bus_id);
ec->resource[i].end -= ec->resource[i].start;
ec->resource[i].start = 0;
+ ec->resource[i].flags = 0;
}
}
+
+ nomem:
+ return ec;
}
static ssize_t ecard_show_irq(struct device *dev, char *buf)
return sprintf(buf, "%u\n", ec->irq);
}
-static DEVICE_ATTR(irq, S_IRUGO, ecard_show_irq, NULL);
-
static ssize_t ecard_show_dma(struct device *dev, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%u\n", ec->dma);
}
-static DEVICE_ATTR(dma, S_IRUGO, ecard_show_dma, NULL);
-
static ssize_t ecard_show_resources(struct device *dev, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
return str - buf;
}
-static DEVICE_ATTR(resource, S_IRUGO, ecard_show_resources, NULL);
-
static ssize_t ecard_show_vendor(struct device *dev, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%u\n", ec->cid.manufacturer);
}
-static DEVICE_ATTR(vendor, S_IRUGO, ecard_show_vendor, NULL);
-
static ssize_t ecard_show_device(struct device *dev, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%u\n", ec->cid.product);
}
-static DEVICE_ATTR(device, S_IRUGO, ecard_show_device, NULL);
+static ssize_t ecard_show_type(struct device *dev, char *buf)
+{
+ struct expansion_card *ec = ECARD_DEV(dev);
+ return sprintf(buf, "%s\n", ec->type == ECARD_EASI ? "EASI" : "IOC");
+}
+
+static struct device_attribute ecard_dev_attrs[] = {
+ __ATTR(device, S_IRUGO, ecard_show_device, NULL),
+ __ATTR(dma, S_IRUGO, ecard_show_dma, NULL),
+ __ATTR(irq, S_IRUGO, ecard_show_irq, NULL),
+ __ATTR(resource, S_IRUGO, ecard_show_resources, NULL),
+ __ATTR(type, S_IRUGO, ecard_show_type, NULL),
+ __ATTR(vendor, S_IRUGO, ecard_show_vendor, NULL),
+ __ATTR_NULL,
+};
int ecard_request_resources(struct expansion_card *ec)
ecard_t **ecp;
ecard_t *ec;
struct ex_ecid cid;
- int i, rc = -ENOMEM;
+ int i, rc;
- ec = kmalloc(sizeof(ecard_t), GFP_KERNEL);
- if (!ec)
+ ec = ecard_alloc_card(type, slot);
+ if (IS_ERR(ec)) {
+ rc = PTR_ERR(ec);
goto nomem;
-
- memset(ec, 0, sizeof(ecard_t));
-
- ec->slot_no = slot;
- ec->type = type;
- ec->irq = NO_IRQ;
- ec->fiq = NO_IRQ;
- ec->dma = NO_DMA;
- ec->card_desc = NULL;
- ec->ops = &ecard_default_ops;
+ }
rc = -ENODEV;
if ((ec->podaddr = ecard_address(ec, type, ECARD_SYNC)) == 0)
ec->cid.fiqmask = cid.r_fiqmask;
ec->cid.fiqoff = ecard_gets24(cid.r_fiqoff);
ec->fiqaddr =
- ec->irqaddr = (unsigned char *)ioaddr(ec->podaddr);
+ ec->irqaddr = (void __iomem *)ioaddr(ec->podaddr);
if (ec->cid.is) {
ec->irqmask = ec->cid.irqmask;
break;
}
- snprintf(ec->dev.bus_id, sizeof(ec->dev.bus_id), "ecard%d", slot);
- ec->dev.parent = NULL;
- ec->dev.bus = &ecard_bus_type;
- ec->dev.dma_mask = &ec->dma_mask;
- ec->dma_mask = (u64)0xffffffff;
-
- ecard_init_resources(ec);
-
/*
* hook the interrupt handlers
*/
slot_to_expcard[slot] = ec;
device_register(&ec->dev);
- device_create_file(&ec->dev, &dev_attr_dma);
- device_create_file(&ec->dev, &dev_attr_irq);
- device_create_file(&ec->dev, &dev_attr_resource);
- device_create_file(&ec->dev, &dev_attr_vendor);
- device_create_file(&ec->dev, &dev_attr_device);
return 0;
-nodev:
- kfree(ec);
-nomem:
+ nodev:
+ ecard_free_card(ec);
+ nomem:
return rc;
}
if (drv->shutdown)
drv->shutdown(ec);
ecard_release(ec);
- req.fn = ecard_task_reset;
- req.ec = ec;
- ecard_call(&req);
+
+ /*
+ * If this card has a loader, call the reset handler.
+ */
+ if (ec->loader) {
+ req.fn = ecard_task_reset;
+ req.ec = ec;
+ ecard_call(&req);
+ }
}
int ecard_register_driver(struct ecard_driver *drv)
}
struct bus_type ecard_bus_type = {
- .name = "ecard",
- .match = ecard_match,
+ .name = "ecard",
+ .dev_attrs = ecard_dev_attrs,
+ .match = ecard_match,
};
static int ecard_bus_init(void)
postcore_initcall(ecard_bus_init);
EXPORT_SYMBOL(ecard_readchunk);
-EXPORT_SYMBOL(ecard_address);
+EXPORT_SYMBOL(__ecard_address);
EXPORT_SYMBOL(ecard_register_driver);
EXPORT_SYMBOL(ecard_remove_driver);
EXPORT_SYMBOL(ecard_bus_type);