source: mainline/uspace/lib/libdrv/include/driver.h@ f031713

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since f031713 was f658458, checked in by Lenka Trochtova <trochtova.lenka@…>, 15 years ago

parts of generic char interface, fixed some bugs

  • Property mode set to 100644
File size: 7.4 KB
RevLine 
[c16cf62]1/*
[a1769ee]2 * Copyright (c) 2010 Lenka Trochtova
[c16cf62]3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libdrv
30 * @{
31 */
32/** @file
33 */
34#ifndef LIBDRV_DRIVER_H_
35#define LIBDRV_DRIVER_H_
36
[084ff99]37
38#include <adt/list.h>
[7f8b581]39#include <ipc/ipc.h>
[bda60d9]40#include <ipc/devman.h>
[a1769ee]41#include <ipc/dev_iface.h>
[3843ecb]42#include <device/hw_res.h>
[25a7e11d]43#include <device/char.h>
[52b7b1bb]44#include <assert.h>
[cfe7716]45#include <ddi.h>
46#include <libarch/ddi.h>
47#include <fibril_synch.h>
48#include <malloc.h>
[084ff99]49
[a1769ee]50struct device;
51typedef struct device device_t;
52
53// device interface
54
55// first two parameters: device and interface structure registered by the devices driver
56typedef void remote_iface_func_t(device_t*, void *, ipc_callid_t, ipc_call_t *);
57typedef remote_iface_func_t *remote_iface_func_ptr_t;
58
59typedef struct {
[52b7b1bb]60 size_t method_count;
[a1769ee]61 remote_iface_func_ptr_t *methods;
62} remote_iface_t;
63
64typedef struct {
65 remote_iface_t * ifaces[DEV_IFACE_COUNT];
66} iface_dipatch_table_t;
67
68
[3843ecb]69static inline bool is_valid_iface_idx(int idx)
[a1769ee]70{
[3843ecb]71 return 0 <= idx && idx < DEV_IFACE_MAX;
[a1769ee]72}
73
[3843ecb]74remote_iface_t* get_remote_iface(int idx);
[52b7b1bb]75remote_iface_func_ptr_t get_remote_method(remote_iface_t *rem_iface, ipcarg_t iface_method_idx);
76
77
[3843ecb]78// device class
79
80/** Devices belonging to the same class should implement the same set of interfaces.*/
81typedef struct device_class {
82 /** Unique identification of the class. */
83 int id;
[25a7e11d]84 /** Optional callback function called when a client is connecting to the device. */
85 int (*open)(device_t *dev);
86 /** Optional callback function called when a client is disconnecting from the device. */
87 void (*close)(device_t *dev);
[3843ecb]88 /** The table of interfaces implemented by the device. */
89 void *interfaces[DEV_IFACE_COUNT];
90} device_class_t;
91
92
[a1769ee]93// device
94
[52b7b1bb]95/** The device. */
[a1769ee]96struct device {
[52b7b1bb]97 /** Globally unique device identifier (assigned to the device by the device manager). */
[bda60d9]98 device_handle_t handle;
[5e598e0]99 /** The phone to the parent device driver (if it is different from this driver).*/
[9a66bc2e]100 int parent_phone;
[5e598e0]101 /** Parent device if handled by this driver, NULL otherwise. */
102 device_t *parent;
[52b7b1bb]103 /** The device's name.*/
[bda60d9]104 const char *name;
[52b7b1bb]105 /** The list of device ids for device-to-driver matching.*/
[bda60d9]106 match_id_list_t match_ids;
[52b7b1bb]107 /** The device driver's data associated with this device.*/
[eff1a590]108 void *driver_data;
[3843ecb]109 /** Device class consist of class id and table of interfaces supported by the device.*/
110 device_class_t *class;
[52b7b1bb]111 /** Pointer to the previous and next device in the list of devices handled by the driver */
[084ff99]112 link_t link;
[a1769ee]113};
[c16cf62]114
[a1769ee]115
116// driver
117
[52b7b1bb]118/** Generic device driver operations. */
[a1769ee]119typedef struct driver_ops {
[52b7b1bb]120 /** Callback method for passing a new device to the device driver.*/
[df747b9c]121 int (*add_device)(device_t *dev);
[c16cf62]122 // TODO add other generic driver operations
123} driver_ops_t;
124
[52b7b1bb]125/** The driver structure.*/
[c16cf62]126typedef struct driver {
[52b7b1bb]127 /** The name of the device driver. */
[c16cf62]128 const char *name;
[52b7b1bb]129 /** Generic device driver operations. */
[c16cf62]130 driver_ops_t *driver_ops;
131} driver_t;
132
133int driver_main(driver_t *drv);
134
[52b7b1bb]135/** Create new device structure.
136 *
137 * @return the device structure.
138 */
[7707954]139static inline device_t * create_device()
140{
141 device_t *dev = malloc(sizeof(device_t));
142 if (NULL != dev) {
143 memset(dev, 0, sizeof(device_t));
[5af21c5]144 init_match_ids(&dev->match_ids);
145 }
[7707954]146 return dev;
147}
148
[52b7b1bb]149/** Delete device structure.
150 *
151 * @param dev the device structure.
152 */
[a1769ee]153static inline void delete_device(device_t *dev)
154{
[bda60d9]155 clean_match_ids(&dev->match_ids);
156 if (NULL != dev->name) {
157 free(dev->name);
158 }
159 free(dev);
160}
[7707954]161
[3843ecb]162static inline void * device_get_iface(device_t *dev, dev_inferface_idx_t idx)
[a1769ee]163{
[3843ecb]164 assert(is_valid_iface_idx(idx));
[f658458]165 if (NULL == dev->class) {
166 return NULL;
167 }
[3843ecb]168 return dev->class->interfaces[idx];
[52b7b1bb]169}
170
[df747b9c]171int child_device_register(device_t *child, device_t *parent);
[7707954]172
[cfe7716]173// interrupts
174
175typedef void interrupt_handler_t(device_t *dev, ipc_callid_t iid, ipc_call_t *icall);
176
177typedef struct interrupt_context {
178 int id;
179 device_t *dev;
180 int irq;
181 interrupt_handler_t *handler;
182 link_t link;
183} interrupt_context_t;
184
185typedef struct interrupt_context_list {
186 int curr_id;
187 link_t contexts;
188 fibril_mutex_t mutex;
189} interrupt_context_list_t;
190
191static inline interrupt_context_t * create_interrupt_context()
192{
193 interrupt_context_t *ctx = (interrupt_context_t *)malloc(sizeof(interrupt_context_t));
194 if (NULL != ctx) {
195 memset(ctx, 0, sizeof(interrupt_context_t));
196 }
197 return ctx;
198}
199
200static inline void delete_interrupt_context(interrupt_context_t *ctx)
201{
202 if (NULL != ctx) {
203 free(ctx);
204 }
205}
206
207static inline void init_interrupt_context_list(interrupt_context_list_t *list)
208{
209 memset(list, 0, sizeof(interrupt_context_list_t));
210 fibril_mutex_initialize(&list->mutex);
211 list_initialize(&list->contexts);
212}
213
214static inline void add_interrupt_context(interrupt_context_list_t *list, interrupt_context_t *ctx)
215{
216 fibril_mutex_lock(&list->mutex);
217
218 ctx->id = list->curr_id++;
219 list_append(&ctx->link, &list->contexts);
220
221 fibril_mutex_unlock(&list->mutex);
222}
223
224static inline void remove_interrupt_context(interrupt_context_list_t *list, interrupt_context_t *ctx)
225{
226 fibril_mutex_lock(&list->mutex);
227
228 list_remove(&ctx->link);
229
230 fibril_mutex_unlock(&list->mutex);
231}
232
233static inline interrupt_context_t *find_interrupt_context_by_id(interrupt_context_list_t *list, int id)
234{
235 fibril_mutex_lock(&list->mutex);
236 link_t *link = list->contexts.next;
237 interrupt_context_t *ctx;
238
239 while (link != &list->contexts) {
240 ctx = list_get_instance(link, interrupt_context_t, link);
241 if (id == ctx->id) {
242 fibril_mutex_unlock(&list->mutex);
243 return ctx;
244 }
245 link = link->next;
246 }
247 fibril_mutex_unlock(&list->mutex);
248 return NULL;
249}
250
251static inline interrupt_context_t *find_interrupt_context(interrupt_context_list_t *list, device_t *dev, int irq)
252{
253 fibril_mutex_lock(&list->mutex);
254 link_t *link = list->contexts.next;
255 interrupt_context_t *ctx;
256
257 while (link != &list->contexts) {
258 ctx = list_get_instance(link, interrupt_context_t, link);
259 if (irq == ctx->irq && dev == ctx->dev) {
260 fibril_mutex_unlock(&list->mutex);
261 return ctx;
262 }
263 link = link->next;
264 }
265 fibril_mutex_unlock(&list->mutex);
266 return NULL;
267}
[7707954]268
[7f8b581]269int register_interrupt_handler(device_t *dev, int irq, interrupt_handler_t *handler, irq_code_t *pseudocode);
270int unregister_interrupt_handler(device_t *dev, int irq);
271
[c16cf62]272#endif
273
274/**
275 * @}
[a1769ee]276 */
Note: See TracBrowser for help on using the repository browser.