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
Line 
1/*
2 * Copyright (c) 2010 Lenka Trochtova
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
37
38#include <adt/list.h>
39#include <ipc/ipc.h>
40#include <ipc/devman.h>
41#include <ipc/dev_iface.h>
42#include <device/hw_res.h>
43#include <device/char.h>
44#include <assert.h>
45#include <ddi.h>
46#include <libarch/ddi.h>
47#include <fibril_synch.h>
48#include <malloc.h>
49
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 {
60 size_t method_count;
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
69static inline bool is_valid_iface_idx(int idx)
70{
71 return 0 <= idx && idx < DEV_IFACE_MAX;
72}
73
74remote_iface_t* get_remote_iface(int idx);
75remote_iface_func_ptr_t get_remote_method(remote_iface_t *rem_iface, ipcarg_t iface_method_idx);
76
77
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;
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);
88 /** The table of interfaces implemented by the device. */
89 void *interfaces[DEV_IFACE_COUNT];
90} device_class_t;
91
92
93// device
94
95/** The device. */
96struct device {
97 /** Globally unique device identifier (assigned to the device by the device manager). */
98 device_handle_t handle;
99 /** The phone to the parent device driver (if it is different from this driver).*/
100 int parent_phone;
101 /** Parent device if handled by this driver, NULL otherwise. */
102 device_t *parent;
103 /** The device's name.*/
104 const char *name;
105 /** The list of device ids for device-to-driver matching.*/
106 match_id_list_t match_ids;
107 /** The device driver's data associated with this device.*/
108 void *driver_data;
109 /** Device class consist of class id and table of interfaces supported by the device.*/
110 device_class_t *class;
111 /** Pointer to the previous and next device in the list of devices handled by the driver */
112 link_t link;
113};
114
115
116// driver
117
118/** Generic device driver operations. */
119typedef struct driver_ops {
120 /** Callback method for passing a new device to the device driver.*/
121 int (*add_device)(device_t *dev);
122 // TODO add other generic driver operations
123} driver_ops_t;
124
125/** The driver structure.*/
126typedef struct driver {
127 /** The name of the device driver. */
128 const char *name;
129 /** Generic device driver operations. */
130 driver_ops_t *driver_ops;
131} driver_t;
132
133int driver_main(driver_t *drv);
134
135/** Create new device structure.
136 *
137 * @return the device structure.
138 */
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));
144 init_match_ids(&dev->match_ids);
145 }
146 return dev;
147}
148
149/** Delete device structure.
150 *
151 * @param dev the device structure.
152 */
153static inline void delete_device(device_t *dev)
154{
155 clean_match_ids(&dev->match_ids);
156 if (NULL != dev->name) {
157 free(dev->name);
158 }
159 free(dev);
160}
161
162static inline void * device_get_iface(device_t *dev, dev_inferface_idx_t idx)
163{
164 assert(is_valid_iface_idx(idx));
165 if (NULL == dev->class) {
166 return NULL;
167 }
168 return dev->class->interfaces[idx];
169}
170
171int child_device_register(device_t *child, device_t *parent);
172
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}
268
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
272#endif
273
274/**
275 * @}
276 */
Note: See TracBrowser for help on using the repository browser.