| [5] | 1 | /* | 
|---|
 | 2 |  * chdev.h - channel device (chdev) descriptor definition. | 
|---|
 | 3 |  *  | 
|---|
 | 4 |  * Authors  Alain Greiner    (2016) | 
|---|
 | 5 |  * | 
|---|
 | 6 |  * Copyright (c) UPMC Sorbonne Universites | 
|---|
 | 7 |  * | 
|---|
 | 8 |  * This file is part of ALMOS-MKH | 
|---|
 | 9 |  * | 
|---|
 | 10 |  * ALMOS-MKH is free software; you can redistribute it and/or modify it | 
|---|
 | 11 |  * under the terms of the GNU General Public License as published by | 
|---|
 | 12 |  * the Free Software Foundation; version 2.0 of the License. | 
|---|
 | 13 |  * | 
|---|
 | 14 |  * ALMOS-MKH is distributed in the hope that it will be useful, but | 
|---|
 | 15 |  * WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
 | 16 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|---|
 | 17 |  * General Public License for more details. | 
|---|
 | 18 |  * | 
|---|
 | 19 |  * You should have received a copy of the GNU General Public License | 
|---|
 | 20 |  * along with ALMOS-MKH; if not, write to the Free Software Foundation, | 
|---|
 | 21 |  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 
|---|
 | 22 |  */ | 
|---|
 | 23 |  | 
|---|
 | 24 | #ifndef _CHDEV_H_ | 
|---|
 | 25 | #define _CHDEV_H_ | 
|---|
 | 26 |  | 
|---|
| [14] | 27 | #include <kernel_config.h> | 
|---|
| [5] | 28 | #include <hal_types.h> | 
|---|
 | 29 | #include <xlist.h> | 
|---|
 | 30 | #include <metafs.h> | 
|---|
 | 31 | #include <remote_spinlock.h> | 
|---|
 | 32 | #include <dev_ioc.h> | 
|---|
 | 33 | #include <dev_nic.h> | 
|---|
 | 34 | #include <dev_icu.h> | 
|---|
 | 35 | #include <dev_pic.h> | 
|---|
 | 36 | #include <dev_fbf.h> | 
|---|
 | 37 |  | 
|---|
 | 38 | /****************************************************************************************** | 
|---|
 | 39 |  *       Channel Device descriptor definition | 
|---|
 | 40 |  * | 
|---|
 | 41 |  * This file defines the kernel representation of a generic (i.e. implementation | 
|---|
 | 42 |  * independant) Channel Device descriptor (in brief "chdev"). | 
|---|
| [23] | 43 |  * ALMOS-MKH supports multi-channels peripherals, and defines one separated chdev  | 
|---|
 | 44 |  * descriptor for each channel (and for each RX/TX direction for the NIC device). | 
|---|
| [5] | 45 |  * Each chdev contains a waiting queue, registering the "client threads" requests, | 
|---|
 | 46 |  * and an associated "server thread", handling these requests. | 
|---|
 | 47 |  * These descriptors are physically distributed on all clusters to minimize contention. | 
|---|
 | 48 |  * Therefore a given I/O operation involve generally three clusters: | 
|---|
 | 49 |  * - the client cluster, containing the client thread, | 
|---|
 | 50 |  * - the server cluster, containing the chdev and the client thread, | 
|---|
 | 51 |  * - the I/O cluster containing the physical device. | 
|---|
 | 52 |  *****************************************************************************************/ | 
|---|
 | 53 |  | 
|---|
 | 54 | /****  Forward declarations  ****/ | 
|---|
 | 55 |  | 
|---|
 | 56 | struct  chdev_s; | 
|---|
 | 57 | struct  thread_s; | 
|---|
 | 58 | struct  boot_info_s; | 
|---|
 | 59 |  | 
|---|
 | 60 | /****************************************************************************************** | 
|---|
 | 61 |  * These macros extract the functionality and the implementation from the peripheral type. | 
|---|
 | 62 |  *****************************************************************************************/ | 
|---|
 | 63 |   | 
|---|
 | 64 | #define FUNC_FROM_TYPE( type )    ((uint32_t)(type>>16)) | 
|---|
 | 65 | #define IMPL_FROM_TYPE( type )    ((uint32_t)(type & 0x0000FFFF)) | 
|---|
 | 66 |  | 
|---|
 | 67 | /****************************************************************************************** | 
|---|
 | 68 |  * This define the generic prototypes for the three functions that must be defined | 
|---|
 | 69 |  * by all drivers implementing a generic device: | 
|---|
 | 70 |  * - "init"    : device initialisation. | 
|---|
 | 71 |  * - "cmd"     : start an I/O operation. | 
|---|
 | 72 |  * - "isr"     : complete an I/O operation. | 
|---|
 | 73 |  * The "init" function is called by kernel_init() to initialise the hardware device. | 
|---|
 | 74 |  * The "cmd" and "isr" are registered in the generic chdev descriptor by kernel_init(), | 
|---|
 | 75 |  * and are called to start and complete an I/O operation.   | 
|---|
 | 76 | *****************************************************************************************/ | 
|---|
 | 77 |  | 
|---|
 | 78 | typedef void (dev_ini_t) ( xptr_t dev );       | 
|---|
 | 79 | typedef void (dev_cmd_t) ( xptr_t thread );   | 
|---|
 | 80 | typedef void (dev_isr_t) ( struct chdev_s * dev );   | 
|---|
 | 81 |  | 
|---|
 | 82 | /****************************************************************************************** | 
|---|
 | 83 |  * This enum defines the supported generic device types. | 
|---|
 | 84 |  * These types are functionnal types: all (architecture specific) implementations  | 
|---|
 | 85 |  * provide the same set of operations and the same driver API. | 
|---|
 | 86 |  * This enum must be consistent with the enum in files arch_info.h, and arch_class.py. | 
|---|
 | 87 |  *****************************************************************************************/ | 
|---|
 | 88 |   | 
|---|
 | 89 | enum dev_func_type  | 
|---|
 | 90 | { | 
|---|
 | 91 |         DEV_FUNC_RAM   =  0, | 
|---|
 | 92 |         DEV_FUNC_ROM   =  1, | 
|---|
 | 93 |         DEV_FUNC_FBF   =  2, | 
|---|
 | 94 |     DEV_FUNC_IOB   =  3, | 
|---|
 | 95 |     DEV_FUNC_IOC   =  4, | 
|---|
 | 96 |         DEV_FUNC_MMC   =  5, | 
|---|
 | 97 |         DEV_FUNC_DMA   =  6, | 
|---|
 | 98 |         DEV_FUNC_NIC   =  7, | 
|---|
 | 99 |         DEV_FUNC_TIM   =  8, | 
|---|
 | 100 |         DEV_FUNC_TXT   =  9, | 
|---|
 | 101 |     DEV_FUNC_ICU   = 10, | 
|---|
 | 102 |     DEV_FUNC_PIC   = 11, | 
|---|
 | 103 |  | 
|---|
 | 104 |     DEV_FUNC_NR    = 12, | 
|---|
 | 105 | }; | 
|---|
 | 106 |  | 
|---|
 | 107 | /****************************************************************************************** | 
|---|
 | 108 |  * This structure defines a chdev descriptor. | 
|---|
| [23] | 109 |  * For multi-channels device, there is one chdev descriptor per channel. | 
|---|
| [5] | 110 |  * This structure is NOT replicated, and can be located in any cluster. | 
|---|
 | 111 |  * One kernel thread, in charge of handling the commands registered in the waiting queue | 
|---|
 | 112 |  * of client threads is associated to each chdev descriptor (not for ICU, PIC, IOB). | 
|---|
 | 113 |  * For each device type ***, the specific extensions are defined in the "dev_***.h" file. | 
|---|
 | 114 |  *****************************************************************************************/ | 
|---|
 | 115 |  | 
|---|
 | 116 | typedef struct chdev_s | 
|---|
 | 117 | { | 
|---|
 | 118 |         uint32_t             func;        /*! peripheral functionnal type                    */ | 
|---|
 | 119 |         uint32_t             impl;        /*! peripheral inplementation subtype              */ | 
|---|
 | 120 |     uint32_t             channel;     /*! channel index                                  */ | 
|---|
 | 121 |     bool_t               is_rx;       /*! relevant for NIC peripheral channels only      */ | 
|---|
| [23] | 122 |         xptr_t               base;        /*! extended pointer on channel segment paddr      */ | 
|---|
 | 123 |     char                 name[16];    /*! name (required by DEVFS)                       */ | 
|---|
| [5] | 124 |  | 
|---|
 | 125 |     dev_cmd_t          * cmd;         /*! local pointer on driver command function       */ | 
|---|
 | 126 |     dev_isr_t          * isr;         /*! local pointer on driver ISR function           */   | 
|---|
 | 127 |     struct thread_s    * server;      /*! local pointer on associated server thread      */ | 
|---|
 | 128 |  | 
|---|
 | 129 |     uint32_t             irq_type;    /*! associated IRQ type in local ICU               */ | 
|---|
 | 130 |     uint32_t             irq_id;      /*! associated IRQ index in local ICU              */ | 
|---|
 | 131 |  | 
|---|
 | 132 |     metafs_t             node;        /*! Metafs node associated with this device        */ | 
|---|
 | 133 |  | 
|---|
 | 134 |         remote_spinlock_t    wait_lock;   /*! lock protecting exclusive access to queue      */ | 
|---|
 | 135 |     xlist_entry_t        wait_root;   /*! root of waiting threads queue                  */ | 
|---|
 | 136 |  | 
|---|
 | 137 |     union | 
|---|
 | 138 |     { | 
|---|
 | 139 |         ioc_extend_t     ioc;         /*! IOC specific extension                         */ | 
|---|
 | 140 |         nic_extend_t     nic;         /*! NIC specific extension                         */ | 
|---|
 | 141 |         icu_extend_t     icu;         /*! ICU specific extension                         */ | 
|---|
 | 142 |         pic_extend_t     pic;         /*! PIC specific extension                         */ | 
|---|
 | 143 |         fbf_extend_t     fbf;         /*! FBF specific extension                         */ | 
|---|
 | 144 |     }  | 
|---|
 | 145 |     ext; | 
|---|
 | 146 | } | 
|---|
 | 147 | chdev_t; | 
|---|
 | 148 |  | 
|---|
 | 149 | /****************************************************************************************** | 
|---|
 | 150 |  * This structure defines the channel_devices descriptors directory. | 
|---|
 | 151 |  * Each entry in this structure contains an extended pointer on a chdev descriptor. | 
|---|
 | 152 |  * There is one entry per channel OR per cluster, depending on peripheral type. | 
|---|
 | 153 |  * This structure is replicated in each cluster, and is initialised during kernel init. | 
|---|
 | 154 |  * It is used for fast access to a device descriptor, from type and channel for an | 
|---|
 | 155 |  * external peripheral, or from type and cluster for a hared internal peripheral. | 
|---|
 | 156 |  * - a "shared" chdev can be accessed by any thread running in any cluster. | 
|---|
 | 157 |  * - a "private" chdev can only be accessed by a thread running in local cluster. | 
|---|
 | 158 |  *****************************************************************************************/ | 
|---|
 | 159 |  | 
|---|
 | 160 | typedef struct chdev_directory_s | 
|---|
 | 161 | { | 
|---|
 | 162 |     xptr_t   iob;                                // external / single channel / shared | 
|---|
 | 163 |     xptr_t   pic;                                // external / single channel / shared | 
|---|
 | 164 |  | 
|---|
 | 165 |     xptr_t   txt[CONFIG_MAX_TXT_CHANNELS];       // external / multi-channels / shared | 
|---|
 | 166 |     xptr_t   ioc[CONFIG_MAX_IOC_CHANNELS];       // external / multi-channels / shared | 
|---|
 | 167 |     xptr_t   fbf[CONFIG_MAX_FBF_CHANNELS];       // external / multi-channels / shared | 
|---|
 | 168 |     xptr_t   nic_rx[CONFIG_MAX_NIC_CHANNELS];    // external / multi-channels / shared | 
|---|
 | 169 |     xptr_t   nic_tx[CONFIG_MAX_NIC_CHANNELS];    // external / multi-channels / shared | 
|---|
 | 170 |  | 
|---|
 | 171 |     xptr_t   icu[CONFIG_MAX_CLUSTERS];           // internal / single channel / shared | 
|---|
 | 172 |     xptr_t   mmc[CONFIG_MAX_CLUSTERS];           // internal / single channel / shared | 
|---|
 | 173 |  | 
|---|
 | 174 |     xptr_t   dma[CONFIG_MAX_DMA_CHANNELS];       // internal / multi-channels / private | 
|---|
 | 175 | } | 
|---|
 | 176 | chdev_directory_t; | 
|---|
 | 177 |  | 
|---|
 | 178 | /****************************************************************************************** | 
|---|
 | 179 |  * This structure defines the input IRQS for the PIC device, that is used by all external | 
|---|
 | 180 |  * peripherals (IOC, NIC, TXT, etc.) to signal completion of an I/O operation. It describes | 
|---|
 | 181 |  * the hardware wiring of IRQs between external peripherals and PIC, as each entry in this | 
|---|
 | 182 |  * structure contains the input IRQ index in PIC. Value is -1 for an unused input. | 
|---|
 | 183 |  * For a multi-channels peripheral, there is one chdev and one IRQ per channel. | 
|---|
 | 184 |  * This structure is replicated in each cluster. It is allocated as a global variable | 
|---|
 | 185 |  * in the kernel_init.c file, and is initialised during kernel init. | 
|---|
 | 186 |  *****************************************************************************************/ | 
|---|
 | 187 |  | 
|---|
 | 188 | typedef struct chdev_pic_input_s | 
|---|
 | 189 | { | 
|---|
 | 190 |     uint32_t   txt[CONFIG_MAX_TXT_CHANNELS]; | 
|---|
 | 191 |     uint32_t   ioc[CONFIG_MAX_IOC_CHANNELS]; | 
|---|
 | 192 |     uint32_t   nic_rx[CONFIG_MAX_NIC_CHANNELS]; | 
|---|
 | 193 |     uint32_t   nic_tx[CONFIG_MAX_NIC_CHANNELS]; | 
|---|
 | 194 | } | 
|---|
 | 195 | chdev_pic_input_t; | 
|---|
 | 196 |  | 
|---|
 | 197 | /****************************************************************************************** | 
|---|
 | 198 |  * This structure defines the input IRQS for the ICU device, that is used by all internal | 
|---|
 | 199 |  * peripherals IRQS (DMA, MMC, etc.) to signal completion of an I/O operation. It describes | 
|---|
 | 200 |  * the hardware wiring of IRQs between internal peripherals and ICU, as each entry in this | 
|---|
 | 201 |  * structure contains the input IRQ index in ICU. Value is -1 for an unused input. | 
|---|
 | 202 |  * For a multi-channels peripheral, there is one chdev and one IRQ per channel. | 
|---|
 | 203 |  * This structure is replicated in each cluster. It is allocated as a global variable | 
|---|
 | 204 |  * in the kernel_init.c file, and is initialised during kernel init. | 
|---|
 | 205 |  *****************************************************************************************/ | 
|---|
 | 206 |  | 
|---|
 | 207 | typedef struct chdev_icu_input_s | 
|---|
 | 208 | { | 
|---|
 | 209 |     uint32_t   dma[CONFIG_MAX_DMA_CHANNELS]; | 
|---|
 | 210 |     uint32_t   mmc;                             // MMC is single channel | 
|---|
 | 211 | } | 
|---|
 | 212 | chdev_icu_input_t; | 
|---|
 | 213 |  | 
|---|
 | 214 | /****************************************************************************************** | 
|---|
 | 215 |  * This function display relevant values for a chdev descriptor. | 
|---|
 | 216 |  ****************************************************************************************** | 
|---|
 | 217 |  * @ chdev   : pointer on chdev. | 
|---|
 | 218 |  *****************************************************************************************/ | 
|---|
 | 219 | void chdev_print( chdev_t * chdev ); | 
|---|
 | 220 |  | 
|---|
 | 221 | /****************************************************************************************** | 
|---|
 | 222 |  * This function returns a printable string for a device functionnal types. | 
|---|
 | 223 |  ****************************************************************************************** | 
|---|
 | 224 |  * @ func_type  : functionnal type. | 
|---|
| [16] | 225 |  * @ return pointer on string. | 
|---|
| [5] | 226 |  *****************************************************************************************/ | 
|---|
 | 227 | char * chdev_func_str( uint32_t func_type ); | 
|---|
 | 228 |  | 
|---|
 | 229 | /****************************************************************************************** | 
|---|
 | 230 |  * This  function allocates memory and initializes a chdev descriptor in local cluster, | 
|---|
 | 231 |  * from arguments values.  It should be called by a local thread.  | 
|---|
 | 232 |  * The device specific fields are initialised later. | 
|---|
 | 233 |  ****************************************************************************************** | 
|---|
 | 234 |  * @ func      : functionnal type. | 
|---|
 | 235 |  * @ impl      : implementation type. | 
|---|
 | 236 |  * @ channel   : channel index / for multi-channels peripherals. | 
|---|
 | 237 |  * @ is_rx     : for NIC peripheral / NIC RX if true / NIC TX if false. | 
|---|
 | 238 |  * @ base      : extended pointer on peripheral segment base. | 
|---|
 | 239 |  * @ return a local pointer on created chdev / return NULL if failure. | 
|---|
 | 240 |  *****************************************************************************************/ | 
|---|
 | 241 | chdev_t * chdev_create( uint32_t    func, | 
|---|
 | 242 |                         uint32_t    impl, | 
|---|
 | 243 |                         uint32_t    channel, | 
|---|
 | 244 |                         bool_t      is_rx, | 
|---|
 | 245 |                         xptr_t      base ); | 
|---|
 | 246 |  | 
|---|
 | 247 | /****************************************************************************************** | 
|---|
 | 248 |  * This function registers a local client thread in the waiting queue of a remote  | 
|---|
 | 249 |  * chdev descriptor, activates (i.e. unblock) the server thread associated to chdev, | 
|---|
 | 250 |  * and blocks itself on the THREAD_BLOCKED_IO condition. | 
|---|
 | 251 |  ****************************************************************************************** | 
|---|
 | 252 |  * @ chdev_xp  : extended pointer on remote chdev descriptor. | 
|---|
 | 253 |  * @ thread    : local pointer on client thread. | 
|---|
 | 254 |  *****************************************************************************************/ | 
|---|
 | 255 | void chdev_register_command( xptr_t            chdev_xp, | 
|---|
 | 256 |                              struct thread_s * thread ); | 
|---|
 | 257 |  | 
|---|
 | 258 | /****************************************************************************************** | 
|---|
 | 259 |  * This function is executed by the server thread associated to a chdev descriptor. | 
|---|
 | 260 |  * It executes an infinite loop to handle sequencially all commands registered by the | 
|---|
 | 261 |  * client threads in the device waiting queue, until the queue is empty. | 
|---|
 | 262 |  * The driver CMD function being blocking, these functions return only when the command | 
|---|
 | 263 |  * is completed. These functions can use either a busy waiting policy, or a descheduling | 
|---|
 | 264 |  * policy, blocking on the THREAD_BLOCKED_IO_ISR condition, and reactivated by the ISR. | 
|---|
 | 265 |  * When the waiting queue is empty, the server thread blocks on the THREAD_BLOCKED_IO_CMD | 
|---|
 | 266 |  * condition and deschedule. It is re-activated by a client thread registering a command. | 
|---|
 | 267 |  ****************************************************************************************** | 
|---|
 | 268 |  * @ chdev   : local pointer on device descriptor. | 
|---|
 | 269 |  *****************************************************************************************/ | 
|---|
 | 270 | void chdev_sequencial_server( chdev_t * chdev ); | 
|---|
 | 271 |  | 
|---|
 | 272 |  | 
|---|
 | 273 | #endif  /* _CHDEV_H_ */ | 
|---|