Source
static unsigned int ace_check_events(struct gendisk *gd, unsigned int clearing)
/*
* Xilinx SystemACE device driver
*
* Copyright 2007 Secret Lab Technologies Ltd.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*/
​
/*
* The SystemACE chip is designed to configure FPGAs by loading an FPGA
* bitstream from a file on a CF card and squirting it into FPGAs connected
* to the SystemACE JTAG chain. It also has the advantage of providing an
* MPU interface which can be used to control the FPGA configuration process
* and to use the attached CF card for general purpose storage.
*
* This driver is a block device driver for the SystemACE.
*
* Initialization:
* The driver registers itself as a platform_device driver at module
* load time. The platform bus will take care of calling the
* ace_probe() method for all SystemACE instances in the system. Any
* number of SystemACE instances are supported. ace_probe() calls
* ace_setup() which initialized all data structures, reads the CF
* id structure and registers the device.
*
* Processing:
* Just about all of the heavy lifting in this driver is performed by
* a Finite State Machine (FSM). The driver needs to wait on a number
* of events; some raised by interrupts, some which need to be polled
* for. Describing all of the behaviour in a FSM seems to be the
* easiest way to keep the complexity low and make it easy to
* understand what the driver is doing. If the block ops or the
* request function need to interact with the hardware, then they
* simply need to flag the request and kick of FSM processing.
*
* The FSM itself is atomic-safe code which can be run from any
* context. The general process flow is:
* 1. obtain the ace->lock spinlock.
* 2. loop on ace_fsm_dostate() until the ace->fsm_continue flag is
* cleared.
* 3. release the lock.
*
* Individual states do not sleep in any way. If a condition needs to
* be waited for then the state much clear the fsm_continue flag and
* either schedule the FSM to be run again at a later time, or expect
* an interrupt to call the FSM when the desired condition is met.
*
* In normal operation, the FSM is processed at interrupt context
* either when the driver's tasklet is scheduled, or when an irq is
* raised by the hardware. The tasklet can be scheduled at any time.
* The request method in particular schedules the tasklet when a new
* request has been indicated by the block layer. Once started, the
* FSM proceeds as far as it can processing the request until it
* needs on a hardware event. At this point, it must yield execution.
*
* A state has two options when yielding execution:
* 1. ace_fsm_yield()
* - Call if need to poll for event.
* - clears the fsm_continue flag to exit the processing loop
* - reschedules the tasklet to run again as soon as possible
* 2. ace_fsm_yieldirq()