static void xsa_complete_request(int uptodate) { XSysAce_Unlock(&SysAce); spin_lock_irq(&xsysace_lock); xsysace_end_request(xsysace_req, uptodate); xsysace_req = 0; spin_unlock_irq(&xsysace_lock); schedule_work(&xsysace_read_write_work); }
/** * * A self-test that simply proves communication to the ACE controller from the * device driver by obtaining an MPU lock, verifying it, then releasing it. * * @param InstancePtr is a pointer to the XSysAce instance to be worked on. * * @return * * XST_SUCCESS if self-test passes, or XST_FAILURE if an error occurs. * * @note * * None. * ******************************************************************************/ int XSysAce_SelfTest(XSysAce * InstancePtr) { int Result; XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); /* * Grab a lock (expect immediate success) */ Result = XSysAce_Lock(InstancePtr, TRUE); if (Result != XST_SUCCESS) { return Result; } /* * Verify the lock was retrieved */ if (!XSysAce_mIsMpuLocked(InstancePtr->BaseAddress)) { return XST_FAILURE; } /* * Release the lock */ XSysAce_Unlock(InstancePtr); /* * Verify the lock was released */ if (XSysAce_mIsMpuLocked(InstancePtr->BaseAddress)) { return XST_FAILURE; } /* * If there are currently any errors on the device, fail self-test */ if (XSysAce_mGetErrorReg(InstancePtr->BaseAddress) != 0) { return XST_FAILURE; } return XST_SUCCESS; }
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; }