Ejemplo n.º 1
0
/**
*
* Identify the CompactFlash device. Retrieves the parameters for the
* CompactFlash storage device. Note that this is a polled read of one sector
* of data. The data is read from the CompactFlash into a byte buffer, which
* is then copied into the XSysAce_CFParameters structure passed in by the
* user.  The copy is necessary since we don't know how the compiler packs
* the XSysAce_CFParameters structure.
*
* An MPU lock, obtained using XSysAce_Lock(), must be granted before calling
* this function. If a lock has not been granted, no action is taken and an
* error is returned.
*
* @param	InstancePtr is a pointer to the XSysAce instance .
* @param	ParamPtr is a pointer to a XSysAce_CFParameters structure where
*		the information for the CompactFlash device will be stored. See
*		xsysace.h for details on the XSysAce_CFParameters structure.
*
* @return
*		- XST_SUCCESS if the identify was done successfully
*		- XST_FAILURE if an error occurs. Use XSysAce_GetErrors() to
*		determine cause.
*		- XST_SYSACE_NO_LOCK if no MPU lock has yet been granted
*		- XST_DEVICE_BUSY if the CompactFlash is not ready for a command
*
* @note		None.
*
* @internal
*
* The identify command has the same protocol as the read sector command
* according to the CompactFlash specification.  However, there is a discepency
* in that same specification on the size of the parameter structure. The word
* addresses defined in the spec indicate the parameter information is a full
* 512 bytes, the same size as a sector. The total bytes defined in the spec,
* however, indicate that the parameter information is only 500 bytes. We
* defined the parameter structure in xsysace.h assuming the parameters are the
* full 512 bytes since that makes sense, and therefore ignored the "Total
* Bytes" column in the spec.
*
* The SectorData variable was made static to avoid putting 512 bytes on the
* stack every time this function is called.
*
******************************************************************************/
int XSysAce_IdentifyCF(XSysAce *InstancePtr, XSysAce_CFParameters * ParamPtr)
{
	int NumRead;
	u32 InterruptsOn;
	static u8 SectorData[XSA_CF_SECTOR_SIZE];

	Xil_AssertNonvoid(InstancePtr != NULL);
	Xil_AssertNonvoid(ParamPtr != NULL);
	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

	/* If a lock has not been granted, return an error */
	if (!XSysAce_IsMpuLocked(InstancePtr->BaseAddress)) {
		return XST_SYSACE_NO_LOCK;
	}

	/* See if the CF is ready for a command */
	if (!XSysAce_IsReadyForCmd(InstancePtr->BaseAddress)) {
		return XST_DEVICE_BUSY;
	}

	/*
	 * If interrupts are enabled, we disable them because we want to do this
	 * identify in polled mode - due to the buffer endian conversion and copy
	 * that takes place.
	 */
	InterruptsOn = XSysAce_IsIntrEnabled(InstancePtr->BaseAddress);
	if (InterruptsOn) {
		XSysAce_DisableInterrupt(InstancePtr);
	}

	/*
	 * Send the identify command
	 */
	XSysAce_RegWrite16(InstancePtr->BaseAddress + XSA_SCCR_OFFSET,
			   XSA_SCCR_IDENTIFY_MASK);

	/* Reset configuration controller (be sure to keep the lock) */
	/* This breaks mvl, beware! */
	/* XSysAce_OrControlReg(InstancePtr->BaseAddress, XSA_CR_CFGRESET_MASK); */

	/*
	 * Read a sector of data from the data buffer. The parameter info is
	 * the same size as a sector.
	 */
	NumRead = XSysAce_ReadDataBuffer(InstancePtr->BaseAddress, SectorData,
					 XSA_CF_SECTOR_SIZE);

	/* Clear reset of configuration controller */
	/* This breaks mvl, beware! */
	/*XSysAce_AndControlReg(InstancePtr->BaseAddress, ~(XSA_CR_CFGRESET_MASK)); */

	/* If interrupts were on, re-enable interrupts (regardless of error) */
	if (InterruptsOn) {
		XSysAce_EnableInterrupt(InstancePtr);
	}

	if (NumRead == 0) {
		/* an error occurred */
		return XST_FAILURE;
	}

	/*
	 * Copy the byte buffer to the parameter structure
	 */
	FillParam(ParamPtr, SectorData);

	return XST_SUCCESS;
}
Ejemplo n.º 2
0
static int xsysace_probe(struct device *dev)
{
	XSysAce_Config xsysace_cfg;
	struct platform_device *pdev = to_platform_device(dev);
	struct resource *irq_res, *regs_res;
	unsigned long remap_size;
	XStatus stat;
	long size;
	XSysAce_CFParameters ident;
	int retval;

	if (!dev)
		return -EINVAL;

	/* Find irq number, map the control registers in */
	irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!regs_res || !irq_res) {
		printk(KERN_ERR "%s #%d: IO resource(s) not found\n",
		       DRIVER_NAME, pdev->id);
		retval = -EFAULT;
		goto failed1;
	}
	xsa_irq = irq_res->start;
	xsa_phys_addr = regs_res->start;
	remap_size = regs_res->end - regs_res->start + 1;
	if (!request_mem_region(regs_res->start, remap_size, DRIVER_NAME)) {
		printk(KERN_ERR
		       "%s #%d: Couldn't lock memory region at 0x%08lX\n",
		       DRIVER_NAME, pdev->id, regs_res->start);
		retval = -EBUSY;
		goto failed1;
	}

	/* Fill in cfg data and add them to the list */
	xsa_remap_size = remap_size;
	xsysace_cfg.DeviceId = pdev->id;
	xsysace_cfg.BaseAddress = (u32) ioremap(regs_res->start, remap_size);
	if (xsysace_cfg.BaseAddress == 0) {
		printk(KERN_ERR
		       "%s #%d: Couldn't ioremap memory at 0x%08lX\n",
		       DRIVER_NAME, pdev->id, regs_res->start);
		retval = -EFAULT;
		goto failed2;
	}

	/* Tell the Xilinx code to bring this SystemACE interface up. */
	down(&cfg_sem);
	if (XSysAce_CfgInitialize
	    (&SysAce, &xsysace_cfg, xsysace_cfg.BaseAddress) != XST_SUCCESS) {
		up(&cfg_sem);
		printk(KERN_ERR
		       "%s #%d: Could not initialize device.\n",
		       DRIVER_NAME, pdev->id);
		retval = -ENODEV;
		goto failed3;
	}
	up(&cfg_sem);

	retval = request_irq(xsa_irq, xsysace_interrupt, 0, DEVICE_NAME, NULL);
	if (retval) {
		printk(KERN_ERR
		       "%s #%d: Couldn't allocate interrupt %d.\n",
		       DRIVER_NAME, pdev->id, xsa_irq);
		goto failed3;
	}

	XSysAce_SetEventHandler(&SysAce, EventHandler, (void *)NULL);
	XSysAce_EnableInterrupt(&SysAce);

	/* Time to identify the drive. */
	while (XSysAce_Lock(&SysAce, 0) == XST_DEVICE_BUSY) ;
	while ((stat =
		XSysAce_IdentifyCF(&SysAce, &ident)) == XST_DEVICE_BUSY) ;
	XSysAce_Unlock(&SysAce);
	if (stat != XST_SUCCESS) {
		printk(KERN_ERR "%s: Could not send identify command.\n",
		       DEVICE_NAME);
		retval = -ENODEV;
		goto failed4;
	}

	/* Fill in what we learned. */
	heads = ident.NumHeads;
	sectors = ident.NumSectorsPerTrack;
	cylinders = ident.NumCylinders;
	size = (long)cylinders *(long)heads *(long)sectors;

	xsysace_queue = blk_init_queue(xsysace_do_request, &xsysace_lock);
	if (!xsysace_queue) {
		retval = -ENODEV;
		goto failed4;
	}

	if (register_blkdev(xsa_major, MAJOR_NAME)) {
		retval = -EBUSY;
		goto failed5;
	}

	xsa_gendisk = alloc_disk(16);
	if (!xsa_gendisk) {
		retval = -ENODEV;
		goto failed6;
	}

	strcpy(xsa_gendisk->disk_name, MAJOR_NAME);
	xsa_gendisk->fops = &xsysace_fops;
	xsa_gendisk->major = xsa_major;
	xsa_gendisk->first_minor = 0;
	xsa_gendisk->minors = 16;
	xsa_gendisk->queue = xsysace_queue;

	set_capacity(xsa_gendisk, size);

	printk(KERN_INFO
	       "%s at 0x%08X mapped to 0x%08X, irq=%d, %ldKB\n",
	       DEVICE_NAME, xsa_phys_addr, SysAce.BaseAddress, xsa_irq,
	       size / 2);

	/* Hook our reset function into system's restart code. */
	if (old_restart == NULL) {
		old_restart = ppc_md.restart;
		ppc_md.restart = xsysace_restart;
	}

	if (proc_init())
		printk(KERN_WARNING "%s: could not register /proc interface.\n",
		       DEVICE_NAME);

	add_disk(xsa_gendisk);

	return 0;		/* success */

      failed6:
	unregister_blkdev(xsa_major, MAJOR_NAME);

      failed5:
	blk_cleanup_queue(xsysace_queue);

      failed4:
	XSysAce_DisableInterrupt(&SysAce);
	free_irq(xsa_irq, NULL);

      failed3:
	iounmap((void *)(xsysace_cfg.BaseAddress));

      failed2:
	release_mem_region(regs_res->start, remap_size);

      failed1:
	return retval;
}