Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
[linux/fpc-iii.git] / drivers / isdn / hardware / eicon / mntfunc.c
blob1cd9affb6058b53484cb2169cda3bf9546f0097e
1 /* $Id: mntfunc.c,v 1.19.6.4 2005/01/31 12:22:20 armin Exp $
3 * Driver for Eicon DIVA Server ISDN cards.
4 * Maint module
6 * Copyright 2000-2003 by Armin Schindler (mac@melware.de)
7 * Copyright 2000-2003 Cytronics & Melware (info@melware.de)
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
14 #include "platform.h"
15 #include "di_defs.h"
16 #include "divasync.h"
17 #include "debug_if.h"
19 extern char *DRIVERRELEASE_MNT;
21 #define DBG_MINIMUM (DL_LOG + DL_FTL + DL_ERR)
22 #define DBG_DEFAULT (DBG_MINIMUM + DL_XLOG + DL_REG)
24 extern void DIVA_DIDD_Read(void *, int);
26 static dword notify_handle;
27 static DESCRIPTOR DAdapter;
28 static DESCRIPTOR MAdapter;
29 static DESCRIPTOR MaintDescriptor =
30 { IDI_DIMAINT, 0, 0, (IDI_CALL) diva_maint_prtComp };
32 extern int diva_os_copy_to_user(void *os_handle, void __user *dst,
33 const void *src, int length);
34 extern int diva_os_copy_from_user(void *os_handle, void *dst,
35 const void __user *src, int length);
37 static void no_printf(unsigned char *x, ...)
39 /* dummy debug function */
42 #include "debuglib.c"
45 * DIDD callback function
47 static void *didd_callback(void *context, DESCRIPTOR *adapter,
48 int removal)
50 if (adapter->type == IDI_DADAPTER) {
51 DBG_ERR(("cb: Change in DAdapter ? Oops ?."));
52 } else if (adapter->type == IDI_DIMAINT) {
53 if (removal) {
54 DbgDeregister();
55 memset(&MAdapter, 0, sizeof(MAdapter));
56 dprintf = no_printf;
57 } else {
58 memcpy(&MAdapter, adapter, sizeof(MAdapter));
59 dprintf = (DIVA_DI_PRINTF) MAdapter.request;
60 DbgRegister("MAINT", DRIVERRELEASE_MNT, DBG_DEFAULT);
62 } else if ((adapter->type > 0) && (adapter->type < 16)) {
63 if (removal) {
64 diva_mnt_remove_xdi_adapter(adapter);
65 } else {
66 diva_mnt_add_xdi_adapter(adapter);
69 return (NULL);
73 * connect to didd
75 static int __init connect_didd(void)
77 int x = 0;
78 int dadapter = 0;
79 IDI_SYNC_REQ req;
80 DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS];
82 DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table));
84 for (x = 0; x < MAX_DESCRIPTORS; x++) {
85 if (DIDD_Table[x].type == IDI_DADAPTER) { /* DADAPTER found */
86 dadapter = 1;
87 memcpy(&DAdapter, &DIDD_Table[x], sizeof(DAdapter));
88 req.didd_notify.e.Req = 0;
89 req.didd_notify.e.Rc =
90 IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY;
91 req.didd_notify.info.callback = (void *)didd_callback;
92 req.didd_notify.info.context = NULL;
93 DAdapter.request((ENTITY *)&req);
94 if (req.didd_notify.e.Rc != 0xff)
95 return (0);
96 notify_handle = req.didd_notify.info.handle;
97 /* Register MAINT (me) */
98 req.didd_add_adapter.e.Req = 0;
99 req.didd_add_adapter.e.Rc =
100 IDI_SYNC_REQ_DIDD_ADD_ADAPTER;
101 req.didd_add_adapter.info.descriptor =
102 (void *) &MaintDescriptor;
103 DAdapter.request((ENTITY *)&req);
104 if (req.didd_add_adapter.e.Rc != 0xff)
105 return (0);
106 } else if ((DIDD_Table[x].type > 0)
107 && (DIDD_Table[x].type < 16)) {
108 diva_mnt_add_xdi_adapter(&DIDD_Table[x]);
111 return (dadapter);
115 * disconnect from didd
117 static void __exit disconnect_didd(void)
119 IDI_SYNC_REQ req;
121 req.didd_notify.e.Req = 0;
122 req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY;
123 req.didd_notify.info.handle = notify_handle;
124 DAdapter.request((ENTITY *)&req);
126 req.didd_remove_adapter.e.Req = 0;
127 req.didd_remove_adapter.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER;
128 req.didd_remove_adapter.info.p_request =
129 (IDI_CALL) MaintDescriptor.request;
130 DAdapter.request((ENTITY *)&req);
134 * read/write maint
136 int maint_read_write(void __user *buf, int count)
138 byte data[128];
139 dword cmd, id, mask;
140 int ret = 0;
142 if (count < (3 * sizeof(dword)))
143 return (-EFAULT);
145 if (diva_os_copy_from_user(NULL, (void *) &data[0],
146 buf, 3 * sizeof(dword))) {
147 return (-EFAULT);
150 cmd = *(dword *)&data[0]; /* command */
151 id = *(dword *)&data[4]; /* driver id */
152 mask = *(dword *)&data[8]; /* mask or size */
154 switch (cmd) {
155 case DITRACE_CMD_GET_DRIVER_INFO:
156 if ((ret = diva_get_driver_info(id, data, sizeof(data))) > 0) {
157 if ((count < ret) || diva_os_copy_to_user
158 (NULL, buf, (void *) &data[0], ret))
159 ret = -EFAULT;
160 } else {
161 ret = -EINVAL;
163 break;
165 case DITRACE_READ_DRIVER_DBG_MASK:
166 if ((ret = diva_get_driver_dbg_mask(id, (byte *) data)) > 0) {
167 if ((count < ret) || diva_os_copy_to_user
168 (NULL, buf, (void *) &data[0], ret))
169 ret = -EFAULT;
170 } else {
171 ret = -ENODEV;
173 break;
175 case DITRACE_WRITE_DRIVER_DBG_MASK:
176 if ((ret = diva_set_driver_dbg_mask(id, mask)) <= 0) {
177 ret = -ENODEV;
179 break;
182 Filter commands will ignore the ID due to fact that filtering affects
183 the B- channel and Audio Tap trace levels only. Also MAINT driver will
184 select the right trace ID by itself
186 case DITRACE_WRITE_SELECTIVE_TRACE_FILTER:
187 if (!mask) {
188 ret = diva_set_trace_filter(1, "*");
189 } else if (mask < sizeof(data)) {
190 if (diva_os_copy_from_user(NULL, data, (char __user *)buf + 12, mask)) {
191 ret = -EFAULT;
192 } else {
193 ret = diva_set_trace_filter((int)mask, data);
195 } else {
196 ret = -EINVAL;
198 break;
200 case DITRACE_READ_SELECTIVE_TRACE_FILTER:
201 if ((ret = diva_get_trace_filter(sizeof(data), data)) > 0) {
202 if (diva_os_copy_to_user(NULL, buf, data, ret))
203 ret = -EFAULT;
204 } else {
205 ret = -ENODEV;
207 break;
209 case DITRACE_READ_TRACE_ENTRY:{
210 diva_os_spin_lock_magic_t old_irql;
211 word size;
212 diva_dbg_entry_head_t *pmsg;
213 byte *pbuf;
215 if (!(pbuf = diva_os_malloc(0, mask))) {
216 return (-ENOMEM);
219 for (;;) {
220 if (!(pmsg =
221 diva_maint_get_message(&size, &old_irql))) {
222 break;
224 if (size > mask) {
225 diva_maint_ack_message(0, &old_irql);
226 ret = -EINVAL;
227 break;
229 ret = size;
230 memcpy(pbuf, pmsg, size);
231 diva_maint_ack_message(1, &old_irql);
232 if ((count < size) ||
233 diva_os_copy_to_user(NULL, buf, (void *) pbuf, size))
234 ret = -EFAULT;
235 break;
237 diva_os_free(0, pbuf);
239 break;
241 case DITRACE_READ_TRACE_ENTRYS:{
242 diva_os_spin_lock_magic_t old_irql;
243 word size;
244 diva_dbg_entry_head_t *pmsg;
245 byte *pbuf = NULL;
246 int written = 0;
248 if (mask < 4096) {
249 ret = -EINVAL;
250 break;
252 if (!(pbuf = diva_os_malloc(0, mask))) {
253 return (-ENOMEM);
256 for (;;) {
257 if (!(pmsg =
258 diva_maint_get_message(&size, &old_irql))) {
259 break;
261 if ((size + 8) > mask) {
262 diva_maint_ack_message(0, &old_irql);
263 break;
266 Write entry length
268 pbuf[written++] = (byte) size;
269 pbuf[written++] = (byte) (size >> 8);
270 pbuf[written++] = 0;
271 pbuf[written++] = 0;
273 Write message
275 memcpy(&pbuf[written], pmsg, size);
276 diva_maint_ack_message(1, &old_irql);
277 written += size;
278 mask -= (size + 4);
280 pbuf[written++] = 0;
281 pbuf[written++] = 0;
282 pbuf[written++] = 0;
283 pbuf[written++] = 0;
285 if ((count < written) || diva_os_copy_to_user(NULL, buf, (void *) pbuf, written)) {
286 ret = -EFAULT;
287 } else {
288 ret = written;
290 diva_os_free(0, pbuf);
292 break;
294 default:
295 ret = -EINVAL;
297 return (ret);
301 * init
303 int __init mntfunc_init(int *buffer_length, void **buffer,
304 unsigned long diva_dbg_mem)
306 if (*buffer_length < 64) {
307 *buffer_length = 64;
309 if (*buffer_length > 512) {
310 *buffer_length = 512;
312 *buffer_length *= 1024;
314 if (diva_dbg_mem) {
315 *buffer = (void *) diva_dbg_mem;
316 } else {
317 while ((*buffer_length >= (64 * 1024))
319 (!(*buffer = diva_os_malloc(0, *buffer_length)))) {
320 *buffer_length -= 1024;
323 if (!*buffer) {
324 DBG_ERR(("init: Can not alloc trace buffer"));
325 return (0);
329 if (diva_maint_init(*buffer, *buffer_length, (diva_dbg_mem == 0))) {
330 if (!diva_dbg_mem) {
331 diva_os_free(0, *buffer);
333 DBG_ERR(("init: maint init failed"));
334 return (0);
337 if (!connect_didd()) {
338 DBG_ERR(("init: failed to connect to DIDD."));
339 diva_maint_finit();
340 if (!diva_dbg_mem) {
341 diva_os_free(0, *buffer);
343 return (0);
345 return (1);
349 * exit
351 void __exit mntfunc_finit(void)
353 void *buffer;
354 int i = 100;
356 DbgDeregister();
358 while (diva_mnt_shutdown_xdi_adapters() && i--) {
359 diva_os_sleep(10);
362 disconnect_didd();
364 if ((buffer = diva_maint_finit())) {
365 diva_os_free(0, buffer);
368 memset(&MAdapter, 0, sizeof(MAdapter));
369 dprintf = no_printf;