linux/drivers/isdn/hardware/eicon/mntfunc.c
<<
>>
Prefs
   1/* $Id: mntfunc.c,v 1.19.6.4 2005/01/31 12:22:20 armin Exp $
   2 *
   3 * Driver for Eicon DIVA Server ISDN cards.
   4 * Maint module
   5 *
   6 * Copyright 2000-2003 by Armin Schindler (mac@melware.de)
   7 * Copyright 2000-2003 Cytronics & Melware (info@melware.de)
   8 *
   9 * This software may be used and distributed according to the terms
  10 * of the GNU General Public License, incorporated herein by reference.
  11 */
  12
  13
  14#include "platform.h"
  15#include "di_defs.h"
  16#include "divasync.h"
  17#include "debug_if.h"
  18
  19extern char *DRIVERRELEASE_MNT;
  20
  21#define DBG_MINIMUM  (DL_LOG + DL_FTL + DL_ERR)
  22#define DBG_DEFAULT  (DBG_MINIMUM + DL_XLOG + DL_REG)
  23
  24extern void DIVA_DIDD_Read(void *, int);
  25
  26static dword notify_handle;
  27static DESCRIPTOR DAdapter;
  28static DESCRIPTOR MAdapter;
  29static DESCRIPTOR MaintDescriptor =
  30    { IDI_DIMAINT, 0, 0, (IDI_CALL) diva_maint_prtComp };
  31
  32extern int diva_os_copy_to_user(void *os_handle, void __user *dst,
  33                                const void *src, int length);
  34extern int diva_os_copy_from_user(void *os_handle, void *dst,
  35                                  const void __user *src, int length);
  36
  37static void no_printf(unsigned char *x, ...)
  38{
  39        /* dummy debug function */
  40}
  41
  42#include "debuglib.c"
  43
  44/*
  45 *  DIDD callback function
  46 */
  47static void *didd_callback(void *context, DESCRIPTOR * adapter,
  48                           int removal)
  49{
  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);
  61                }
  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);
  67                }
  68        }
  69        return (NULL);
  70}
  71
  72/*
  73 * connect to didd
  74 */
  75static int DIVA_INIT_FUNCTION connect_didd(void)
  76{
  77        int x = 0;
  78        int dadapter = 0;
  79        IDI_SYNC_REQ req;
  80        DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS];
  81
  82        DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table));
  83
  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]);
 109                }
 110        }
 111        return (dadapter);
 112}
 113
 114/*
 115 * disconnect from didd
 116 */
 117static void DIVA_EXIT_FUNCTION disconnect_didd(void)
 118{
 119        IDI_SYNC_REQ req;
 120
 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);
 125
 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);
 131}
 132
 133/*
 134 * read/write maint
 135 */
 136int maint_read_write(void __user *buf, int count)
 137{
 138        byte data[128];
 139        dword cmd, id, mask;
 140        int ret = 0;
 141
 142        if (count < (3 * sizeof(dword)))
 143                return (-EFAULT);
 144
 145        if (diva_os_copy_from_user(NULL, (void *) &data[0],
 146                                   buf, 3 * sizeof(dword))) {
 147                return (-EFAULT);
 148        }
 149
 150        cmd = *(dword *) & data[0];     /* command */
 151        id = *(dword *) & data[4];      /* driver id */
 152        mask = *(dword *) & data[8];    /* mask or size */
 153
 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;
 162                }
 163                break;
 164
 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;
 172                }
 173                break;
 174
 175        case DITRACE_WRITE_DRIVER_DBG_MASK:
 176                if ((ret = diva_set_driver_dbg_mask(id, mask)) <= 0) {
 177                        ret = -ENODEV;
 178                }
 179                break;
 180
 181    /*
 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
 185       */
 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);
 194                        }
 195                } else {
 196                        ret = -EINVAL;
 197                }
 198                break;
 199
 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;
 206                }
 207                break;
 208
 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;
 214
 215                        if (!(pbuf = diva_os_malloc(0, mask))) {
 216                                return (-ENOMEM);
 217                        }
 218
 219                        for(;;) {
 220                                if (!(pmsg =
 221                                    diva_maint_get_message(&size, &old_irql))) {
 222                                        break;
 223                                }
 224                                if (size > mask) {
 225                                        diva_maint_ack_message(0, &old_irql);
 226                                        ret = -EINVAL;
 227                                        break;
 228                                }
 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;
 236                        }
 237                        diva_os_free(0, pbuf);
 238                }
 239                break;
 240
 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;
 247
 248                        if (mask < 4096) {
 249                                ret = -EINVAL;
 250                                break;
 251                        }
 252                        if (!(pbuf = diva_os_malloc(0, mask))) {
 253                                return (-ENOMEM);
 254                        }
 255
 256                        for (;;) {
 257                                if (!(pmsg =
 258                                     diva_maint_get_message(&size, &old_irql))) {
 259                                        break;
 260                                }
 261                                if ((size + 8) > mask) {
 262                                        diva_maint_ack_message(0, &old_irql);
 263                                        break;
 264                                }
 265                                /*
 266                                   Write entry length
 267                                 */
 268                                pbuf[written++] = (byte) size;
 269                                pbuf[written++] = (byte) (size >> 8);
 270                                pbuf[written++] = 0;
 271                                pbuf[written++] = 0;
 272                                /*
 273                                   Write message
 274                                 */
 275                                memcpy(&pbuf[written], pmsg, size);
 276                                diva_maint_ack_message(1, &old_irql);
 277                                written += size;
 278                                mask -= (size + 4);
 279                        }
 280                        pbuf[written++] = 0;
 281                        pbuf[written++] = 0;
 282                        pbuf[written++] = 0;
 283                        pbuf[written++] = 0;
 284
 285                        if ((count < written) || diva_os_copy_to_user(NULL, buf, (void *) pbuf, written)) {
 286                                ret = -EFAULT;
 287                        } else {
 288                                ret = written;
 289                        }
 290                        diva_os_free(0, pbuf);
 291                }
 292                break;
 293
 294        default:
 295                ret = -EINVAL;
 296        }
 297        return (ret);
 298}
 299
 300/*
 301 *  init
 302 */
 303int DIVA_INIT_FUNCTION mntfunc_init(int *buffer_length, void **buffer,
 304                                    unsigned long diva_dbg_mem)
 305{
 306        if (*buffer_length < 64) {
 307                *buffer_length = 64;
 308        }
 309        if (*buffer_length > 512) {
 310                *buffer_length = 512;
 311        }
 312        *buffer_length *= 1024;
 313
 314        if (diva_dbg_mem) {
 315                *buffer = (void *) diva_dbg_mem;
 316        } else {
 317                while ((*buffer_length >= (64 * 1024))
 318                       &&
 319                       (!(*buffer = diva_os_malloc (0, *buffer_length)))) {
 320                        *buffer_length -= 1024;
 321                }
 322
 323                if (!*buffer) {
 324                        DBG_ERR(("init: Can not alloc trace buffer"));
 325                        return (0);
 326                }
 327        }
 328
 329        if (diva_maint_init(*buffer, *buffer_length, (diva_dbg_mem == 0))) {
 330                if (!diva_dbg_mem) {
 331                        diva_os_free (0, *buffer);
 332                }
 333                DBG_ERR(("init: maint init failed"));
 334                return (0);
 335        }
 336
 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);
 342                }
 343                return (0);
 344        }
 345        return (1);
 346}
 347
 348/*
 349 *  exit
 350 */
 351void DIVA_EXIT_FUNCTION mntfunc_finit(void)
 352{
 353        void *buffer;
 354        int i = 100;
 355
 356        DbgDeregister();
 357
 358        while (diva_mnt_shutdown_xdi_adapters() && i--) {
 359                diva_os_sleep(10);
 360        }
 361
 362        disconnect_didd();
 363
 364        if ((buffer = diva_maint_finit())) {
 365                diva_os_free (0, buffer);
 366        }
 367
 368        memset(&MAdapter, 0, sizeof(MAdapter));
 369        dprintf = no_printf;
 370}
 371