⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usr_blk_dev.c

📁 包含MMC协议,驱动源码. 在LINUX操作系统下通过.
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Copyright 2005 Motorola, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA   * 02111-1307, USA * *//*! * @file usr_blk_dev.c * * @ingroup usr_blk_dev * * @brief This is the main file for the user block driver. * * <B>Overview:</B><BR> *    The user block driver is a removable media block driver intended to allow * for user space drivers for the media. * *    This driver operates by creating an entry on /proc and using the entry * to communicate commands to user space.  See ::USR_BLK_DEV_CMD_ID_T for a list * of these commands.  Commands are sent from a kernel thread through /proc * to user space.  Once the user space process has completed the command it * responds with a write to the proc entry.  Only one command can be processed * at a time by a user space process and a kernel thread.  A thread is used * for the commands in order to keep the request queue from blocking which is * not allowed. * *    At this time a single thread is used for all devices attached.  This * is not intended to be the final design, but was done to speed up development. * This will be acceptable for systems which implement only one device.  If * more than one device is to be supported, then multiple threads should be * used, one per /proc entry.  This will speed up throughput, since one part * will not block the others. * * There are two different levels of command processing within this driver. * Commands from interrupts, the request queue and general file operations * (open, revalidate, check_media) are placed in the command structure * (usr_blk_dev_cmd_s) within the information structure (::USR_BLK_DEV_INFO_T) * for the device.  These commands are then processed by the kernel thread * (usr_blk_dev_thread()) and sent to user space.  Once they are processed by * user space, the kernel thread copies any return data and informs the source * of the command that it has been completed. * *   Part detection is done via a switch in the socket which is connected to * GPIO on the part.  An interrupt is generated on both the rising edge and the * falling edge of the signal.  Once an interrupt is detected a timer is used * do debounce the signal.  After the signal has achieved a steady state the * interrupt is re-enabled and the timer stopped. * * <B>Devices Created:</B><BR> *    -# /proc/usr_blk_dev0: The read/write interface to the user space driver *       for device 0. *    -# /proc/usr_blk_devn: The read/write interface to the user space driver *       for device n. * <B>Devices Used:</B><BR> *    -# /dev/mmca0: The root for the first detected card in the first slot. *    -# /dev/mmca\<n\>: The partitions of the detected card (up to 8 partitions *       are supported). *    -# /dev/mmcb0: The root for the card in the second slot if detected. *       Additional cards continue to increment the letter (c, d, e, ...). *    -# /dev/mmcb\<n\>: The partitions of the card in the second slot. *       Additional cards continue to increment the letter (c, d, e, ...). * * <B>Command Lifecycle:</B><BR> *    When a command is sent to the user block thread it transitions through * the states described in ::USR_BLK_DEV_CMD_STATE_T.  As they enter a new * state they may wait on a wait queue or wake up another queue as they * complete.  It is necessary for commands to cycle through the states or * they can hold up all subsequent commands. * *    The following describes the states and the wait queues used within them. * The state for the commands are stored in * usr_blk_dev_info[dev_num].cmd[cmd_src].state * * <B>#USR_BLK_DEV_CMD_STATE_NONE:</B><BR> *   This state can be considered the idle state of the driver.  This value sits * in the state variable when the no command is active.  A transition to the * ::USR_BLK_DEV_CMD_STATE_NEW state starts a command executing in the user block * thread.<BR> * * <B>#USR_BLK_DEV_CMD_STATE_NEW:</B><BR> *   This is the state a requester must put in the state value in order to start * a command executing.  In the case of commands which come from locations which * can block the wait queue usr_blk_dev_info[dev_num].cmd[cmd_src].wait_for_completion * must be used before the new command can be added. * * <B>#USR_BLK_DEV_CMD_STATE_THREAD:</B><BR> *   This value is placed in the state control variable as soon as the user block * thread detects the command is new.  It does not wait on any queues. * * <B>#USR_BLK_DEV_CMD_STATE_USR_READ</B><BR> *   When a command is in this state it has woken up the * usr_blk_dev_info[dev_num].wait_for_usr_read queue which controls when user * reads of the /proc entry happen. * * <B>#USR_BLK_DEV_CMD_STATE_USR_WAIT:</B><BR> *   This state is transitioned to as soon as the user process reads the command * from the /proc entry.  The command will remain in this state until the * response is written to the /proc entry from the user driver.  Commands in * this state (as well as the ::USR_BLK_DEV_CMD_STATE_USR_READ) are waiting on * the usr_blk_dev_info[dev_num].wait_for_usr_write queue. * * <B>#USR_BLK_DEV_CMD_STATE_USR_DONE:</B><BR> *   This state is entered as soon as the usr_blk_dev_info[dev_num].wait_for_usr_write * queue is awakened.  At this point the user block thread continues by processing * any necessary data.  If the data was from the request queue * (::USR_BLK_DEV_CMD_SRC_REQ) or an interrupt (::USR_BLK_DEV_CMD_SRC_IRQ) the command * is transitioned to ::USR_BLK_DEV_CMD_STATE_NONE since no more processing is * necessary. If it is not from one of these sources it will wake up the * usr_blk_dev_info[dev_num].cmd[cmd_src].wait_for_thread queue to allow the * requester to process the data. * * <B>#USR_BLK_DEV_CMD_STATE_THREAD_DONE:</B><BR> *   Once the user block thread is done executing a command the * usr_blk_dev_info[dev_num].cmd[cmd_src].wait_for_thread will be awakened and the * requester of the command will transition to this state.  Within this state * the requester will act upon the date returned and set the state back to * #USR_BLK_DEV_CMD_STATE_NONE. * * For more data on the individual commands see the ::USR_BLK_DEV_CMD_ID_T. */#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <stdbool.h>#include <asm/arch/hardware.h>#include <linux/blk.h>#include <linux/blkdev.h>#include <linux/blkpg.h>#include <linux/fs.h>#include <linux/genhd.h>#include <linux/hdreg.h>#include <linux/init.h>#include <asm/irq.h>#include <linux/proc_fs.h>#include <linux/sched.h>#include <linux/poll.h>#include <linux/timer.h>#include <asm/uaccess.h>#include <linux/wait.h>#include <linux/usr_blk_dev.h>/******************************************************************************* Local constants and macros******************************************************************************//*! * @brief The number of successive times the sample of the device attach signal must * match before the device state is changed. */#define USR_BLK_DEV_DEBOUNCE_CNT 4#ifndef CONFIG_ARCH_SCMA11/*! @brief Port to which the media card detect switch is attached. */#define USR_BLK_DEV_DEV1_INT_GPIO 11 /*! @brief Returns non zero if the media card is attached. */# define USR_BLK_DEV_IS_DEV1_ATTACHED ((GPLR(USR_BLK_DEV_DEV1_INT_GPIO) & GPIO_bit(USR_BLK_DEV_DEV1_INT_GPIO)) != 0)#endif/*! @brief The name of the /proc entry as it will appear in the directory /proc. */#define USR_BLK_DEV_PROC_ENTRY_STR  "usr_blk_dev"/*! @brief The number of characters in USR_BLK_DEV_PROC_ENTRY_STR. */#define USR_BLK_DEV_PROC_ENTRY_LEN  11/*! * @brief The number of times the proc entry for a device can be opened. * * The number of times the proc entry for a device can be opened.  This is set * to one since only one user driver is needed to drive a device and if more * than one user process opens the entry, bad things would happen. */#define USR_BLK_DEV_MAX_PROC_OPENS 1/*! @brief Name of the user block device. */#define USR_BLK_DEV_DEVICE_NAME_STR "usr_blk_dev"/*! @brief Support 8 partitions per card. */#define USR_BLK_DEV_SHIFT   3/* @brief The maximum number of sectors which can be included in a single request. */#define USR_BLK_DEV_MAX_SECTORS_PER_REQ 128/*! @brief Used to enable debugging messages to be sent out the system log. *//* #define USR_BLK_DEV_DEBUG *//*! @brief Macro used to send debug messages to the system log. */#ifdef USR_BLK_DEV_DEBUG# define tracemsg(fmt,args...)  printk(__FILE__": %s: "fmt,__func__,##args)#else# define tracemsg(fmt,args...)#endif/*! * @brief Macro to extract the device number from the device node. *  * Each device has 8 minor numbers since* USR_BLK_DEV_SHIFT is currently 3. * This results in the device number being stored in upper bits. */#define USR_BLK_DEV_DEVICE_NR(i_rdev) (MINOR(i_rdev)>>USR_BLK_DEV_SHIFT)/*!  * @brief Timer used to debounce the insertion of a card. * * Only one timer is used for all of the devices. */static struct timer_list usr_blk_dev_timer;/*! * @brief The possible states of the media detection state machine. * * A list of the possible states of the card detection state machine which is * implemented in usr_blk_dev_poll_card_attach(). * * @note Removal is not debounced since a media card may have its power removed * at the point at which it is detected as removed only once.  In this case the * safest thing to do is to reinitialize the card. */typedef enum{    /*! @brief The media is currently not connected. */    USR_BLK_DEV_DEBOUNCE_STATE_REMOVED,    /*!     * @brief The media card has been detected as inserted and is being debounced.     *     * The media card has been detected as inserted at least once.  The number of     * states determines the number of times the card must be detected as inserted     * before it will be reported as such.     */    /* @{ */    USR_BLK_DEV_DEBOUNCE_STATE_INSERTING,    USR_BLK_DEV_DEBOUNCE_STATE_INSERTING1,    USR_BLK_DEV_DEBOUNCE_STATE_INSERTING2,    USR_BLK_DEV_DEBOUNCE_STATE_INSERTING3,    USR_BLK_DEV_DEBOUNCE_STATE_INSERTING4,    /* @} */    /*!     * @brief The card has been debounced as inserted, the driver must be informed.     *     * Once the card is detected as inserted the rest of the driver must be informed.     * However, this may take several iterations if the thread still has not received     * the previous state change.  This state will wait until the thread is ready to     * receive the indication before sending it.     */    USR_BLK_DEV_DEBOUNCE_STATE_UPDATE_INSERT,    /* @brief The media is currently inserted. */    USR_BLK_DEV_DEBOUNCE_STATE_INSERTED,    /* Removal is not debounced, so no REMOVING state exists. */    /*!     * @brief The card has been debounced as removed, the driver must be informed.     *     * Once the card is detected as removed the rest of the driver must be informed.     * However, this may take several iterations if the thread still has not received     * the previous state change.  This state will wait until the thread is ready to     * receive the indication before sending it.     */    USR_BLK_DEV_DEBOUNCE_STATE_UPDATE_REMOVAL} USR_BLK_DEV_DEBOUNCE_STATE_T;/*! * @brief The possible sources of commands for the kernel thread to send. * * There are three different sources of a command from the kernel: *   - The detect interrupt, *   - The request queue, *   - A user process calling open, close, read, write etc. */typedef enum{    USR_BLK_DEV_CMD_SRC_IRQ,  /*!< The command came from the detect interrupt. */    USR_BLK_DEV_CMD_SRC_REQ,  /*!< The command came from the request queue. */    USR_BLK_DEV_CMD_SRC_GEN,  /*!< The command came from a general source which can block. */    USR_BLK_DEV_CMD_SRC__END} USR_BLK_DEV_CMD_SRC_T;/*! * @brief The state of the command being processed. * * A typical command will have the following states.  If the command originated * in an interrupt or from the request queue, it will not progress though the * final states, since there is no need to respond to the calling layer.  Please * note there is a difference between a command which came from the kernel * request queue and once which is being handled by the RW code from within the * thread.  The thread based read write commands progress through all of the * states. */typedef enum{    /*! No command is active. */     USR_BLK_DEV_CMD_STATE_NONE    /*! A command request has been made by one of the three sources. */,    USR_BLK_DEV_CMD_STATE_NEW,    /*! The thread has received the command and has begun to act upon it. */    USR_BLK_DEV_CMD_STATE_THREAD,    /*! The thread is waiting for the user space driver to read the command. */    USR_BLK_DEV_CMD_STATE_USR_READ,    /*!     * The command has been read by the user space process and the kernel thread     * is waiting on the response.     */    USR_BLK_DEV_CMD_STATE_USR_WAIT,    /*!     * The user space process has acted upon the command and written a response     * to the /proc entry.     */    USR_BLK_DEV_CMD_STATE_USR_DONE,     /*!      * The thread has completed operating on the command, and passed the data      * back to the originator of the command.      */    USR_BLK_DEV_CMD_STATE_THREAD_DONE} USR_BLK_DEV_CMD_STATE_T;/*! * @brief Structure which holds information on the devices attached. * * The following is used as an array indexed by the device number to store any * data needed by the driver.  Please see the individual entries for details on * what is stored. */typedef struct{    /*!     * @brief The current state of debouncing for the device.     *      * A simple state machine is used for debouncing the insertion and removal     * of the card.  This is the state counter for that machine.  It can also     * be used to determine the status of the card at any time while running.     */    USR_BLK_DEV_DEBOUNCE_STATE_T debounce_state;    /*!     * @brief Used to track the connection state of the media.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -