static int pcmciamtd_config()

in maps/pcmciamtd.c [462:632]


static int pcmciamtd_config(struct pcmcia_device *link)
{
	struct pcmciamtd_dev *dev = link->priv;
	struct mtd_info *mtd = NULL;
	int ret;
	int i, j = 0;
	static char *probes[] = { "jedec_probe", "cfi_probe" };
	int new_name = 0;

	pr_debug("link=0x%p\n", link);

	card_settings(dev, link, &new_name);

	dev->pcmcia_map.phys = NO_XIP;
	dev->pcmcia_map.copy_from = pcmcia_copy_from_remap;
	dev->pcmcia_map.copy_to = pcmcia_copy_to_remap;
	if (dev->pcmcia_map.bankwidth == 1) {
		dev->pcmcia_map.read = pcmcia_read8_remap;
		dev->pcmcia_map.write = pcmcia_write8_remap;
	} else {
		dev->pcmcia_map.read = pcmcia_read16_remap;
		dev->pcmcia_map.write = pcmcia_write16_remap;
	}
	if(setvpp == 1)
		dev->pcmcia_map.set_vpp = pcmciamtd_set_vpp;

	/* Request a memory window for PCMCIA. Some architeures can map windows
	 * up to the maximum that PCMCIA can support (64MiB) - this is ideal and
	 * we aim for a window the size of the whole card - otherwise we try
	 * smaller windows until we succeed
	 */

	link->resource[2]->flags |=  WIN_MEMORY_TYPE_CM | WIN_ENABLE;
	link->resource[2]->flags |= (dev->pcmcia_map.bankwidth == 1) ?
					WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16;
	link->resource[2]->start = 0;
	link->resource[2]->end = (force_size) ? force_size << 20 :
					MAX_PCMCIA_ADDR;
	dev->win_size = 0;

	do {
		int ret;
		pr_debug("requesting window with size = %luKiB memspeed = %d\n",
			(unsigned long) resource_size(link->resource[2]) >> 10,
			mem_speed);
		ret = pcmcia_request_window(link, link->resource[2], mem_speed);
		pr_debug("ret = %d dev->win_size = %d\n", ret, dev->win_size);
		if(ret) {
			j++;
			link->resource[2]->start = 0;
			link->resource[2]->end = (force_size) ?
					force_size << 20 : MAX_PCMCIA_ADDR;
			link->resource[2]->end >>= j;
		} else {
			pr_debug("Got window of size %luKiB\n", (unsigned long)
				resource_size(link->resource[2]) >> 10);
			dev->win_size = resource_size(link->resource[2]);
			break;
		}
	} while (link->resource[2]->end >= 0x1000);

	pr_debug("dev->win_size = %d\n", dev->win_size);

	if(!dev->win_size) {
		dev_err(&dev->p_dev->dev, "Cannot allocate memory window\n");
		pcmciamtd_release(link);
		return -ENODEV;
	}
	pr_debug("Allocated a window of %dKiB\n", dev->win_size >> 10);

	/* Get write protect status */
	dev->win_base = ioremap(link->resource[2]->start,
				resource_size(link->resource[2]));
	if(!dev->win_base) {
		dev_err(&dev->p_dev->dev, "ioremap(%pR) failed\n",
			link->resource[2]);
		pcmciamtd_release(link);
		return -ENODEV;
	}
	pr_debug("mapped window dev = %p @ %pR, base = %p\n",
	      dev, link->resource[2], dev->win_base);

	dev->offset = 0;
	dev->pcmcia_map.map_priv_1 = (unsigned long)dev;
	dev->pcmcia_map.map_priv_2 = (unsigned long)link->resource[2];

	dev->vpp = (vpp) ? vpp : link->socket->socket.Vpp;
	if(setvpp == 2) {
		link->vpp = dev->vpp;
	} else {
		link->vpp = 0;
	}

	link->config_index = 0;
	pr_debug("Setting Configuration\n");
	ret = pcmcia_enable_device(link);
	if (ret != 0) {
		if (dev->win_base) {
			iounmap(dev->win_base);
			dev->win_base = NULL;
		}
		return -ENODEV;
	}

	if(mem_type == 1) {
		mtd = do_map_probe("map_ram", &dev->pcmcia_map);
	} else if(mem_type == 2) {
		mtd = do_map_probe("map_rom", &dev->pcmcia_map);
	} else {
		for(i = 0; i < ARRAY_SIZE(probes); i++) {
			pr_debug("Trying %s\n", probes[i]);
			mtd = do_map_probe(probes[i], &dev->pcmcia_map);
			if(mtd)
				break;

			pr_debug("FAILED: %s\n", probes[i]);
		}
	}

	if(!mtd) {
		pr_debug("Can not find an MTD\n");
		pcmciamtd_release(link);
		return -ENODEV;
	}

	dev->mtd_info = mtd;
	mtd->owner = THIS_MODULE;

	if(new_name) {
		int size = 0;
		char unit = ' ';
		/* Since we are using a default name, make it better by adding
		 * in the size
		 */
		if(mtd->size < 1048576) { /* <1MiB in size, show size in KiB */
			size = mtd->size >> 10;
			unit = 'K';
		} else {
			size = mtd->size >> 20;
			unit = 'M';
		}
		snprintf(dev->mtd_name, sizeof(dev->mtd_name), "%d%ciB %s", size, unit, "PCMCIA Memory card");
	}

	/* If the memory found is fits completely into the mapped PCMCIA window,
	   use the faster non-remapping read/write functions */
	if(mtd->size <= dev->win_size) {
		pr_debug("Using non remapping memory functions\n");
		dev->pcmcia_map.map_priv_2 = (unsigned long)dev->win_base;
		if (dev->pcmcia_map.bankwidth == 1) {
			dev->pcmcia_map.read = pcmcia_read8;
			dev->pcmcia_map.write = pcmcia_write8;
		} else {
			dev->pcmcia_map.read = pcmcia_read16;
			dev->pcmcia_map.write = pcmcia_write16;
		}
		dev->pcmcia_map.copy_from = pcmcia_copy_from;
		dev->pcmcia_map.copy_to = pcmcia_copy_to;
	}

	if (mtd_device_register(mtd, NULL, 0)) {
		map_destroy(mtd);
		dev->mtd_info = NULL;
		dev_err(&dev->p_dev->dev,
			"Could not register the MTD device\n");
		pcmciamtd_release(link);
		return -ENODEV;
	}
	dev_info(&dev->p_dev->dev, "mtd%d: %s\n", mtd->index, mtd->name);
	return 0;
}