linux/drivers/staging/dgrp/dgrp_dpa_ops.c
<<
>>
Prefs
   1/*
   2 *
   3 * Copyright 1999 Digi International (www.digi.com)
   4 *     James Puzzo <jamesp at digi dot com>
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; either version 2, or (at your option)
   9 * any later version.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
  13 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  14 * PURPOSE.  See the GNU General Public License for more details.
  15 *
  16 */
  17
  18/*
  19 *
  20 *  Filename:
  21 *
  22 *     dgrp_dpa_ops.c
  23 *
  24 *  Description:
  25 *
  26 *     Handle the file operations required for the "dpa" devices.
  27 *     Includes those functions required to register the "dpa" devices
  28 *     in "/proc".
  29 *
  30 *  Author:
  31 *
  32 *     James A. Puzzo
  33 *
  34 */
  35
  36#include <linux/module.h>
  37#include <linux/proc_fs.h>
  38#include <linux/tty.h>
  39#include <linux/poll.h>
  40#include <linux/cred.h>
  41#include <linux/sched.h>
  42#include <linux/ratelimit.h>
  43#include <linux/slab.h>
  44#include <asm/unaligned.h>
  45
  46#include "dgrp_common.h"
  47
  48/* File operation declarations */
  49static int dgrp_dpa_open(struct inode *, struct file *);
  50static int dgrp_dpa_release(struct inode *, struct file *);
  51static ssize_t dgrp_dpa_read(struct file *, char __user *, size_t, loff_t *);
  52static long dgrp_dpa_ioctl(struct file *file, unsigned int cmd,
  53                           unsigned long arg);
  54static unsigned int dgrp_dpa_select(struct file *, struct poll_table_struct *);
  55
  56const struct file_operations dgrp_dpa_ops = {
  57        .owner   =  THIS_MODULE,
  58        .read    =  dgrp_dpa_read,
  59        .poll    =  dgrp_dpa_select,
  60        .unlocked_ioctl =  dgrp_dpa_ioctl,
  61        .open    =  dgrp_dpa_open,
  62        .release =  dgrp_dpa_release,
  63};
  64
  65struct digi_node {
  66        uint    nd_state;               /* Node state: 1 = up, 0 = down. */
  67        uint    nd_chan_count;          /* Number of channels found */
  68        uint    nd_tx_byte;             /* Tx data count */
  69        uint    nd_rx_byte;             /* RX data count */
  70        u8      nd_ps_desc[MAX_DESC_LEN]; /* Description from PS */
  71};
  72
  73#define DIGI_GETNODE      (('d'<<8) | 249)      /* get board info */
  74
  75
  76struct digi_chan {
  77        uint    ch_port;        /* Port number to get info on */
  78        uint    ch_open;        /* 1 if open, 0 if not */
  79        uint    ch_txcount;     /* TX data count  */
  80        uint    ch_rxcount;     /* RX data count  */
  81        uint    ch_s_brate;     /* Realport BRATE */
  82        uint    ch_s_estat;     /* Realport ELAST */
  83        uint    ch_s_cflag;     /* Realport CFLAG */
  84        uint    ch_s_iflag;     /* Realport IFLAG */
  85        uint    ch_s_oflag;     /* Realport OFLAG */
  86        uint    ch_s_xflag;     /* Realport XFLAG */
  87        uint    ch_s_mstat;     /* Realport MLAST */
  88};
  89
  90#define DIGI_GETCHAN      (('d'<<8) | 248)      /* get channel info */
  91
  92
  93struct digi_vpd {
  94        int vpd_len;
  95        char vpd_data[VPDSIZE];
  96};
  97
  98#define DIGI_GETVPD       (('d'<<8) | 246)      /* get VPD info */
  99
 100
 101struct digi_debug {
 102        int onoff;
 103        int port;
 104};
 105
 106#define DIGI_SETDEBUG      (('d'<<8) | 247)     /* set debug info */
 107
 108
 109/*
 110 * dgrp_dpa_open -- open the DPA device for a particular PortServer
 111 */
 112static int dgrp_dpa_open(struct inode *inode, struct file *file)
 113{
 114        struct nd_struct *nd;
 115        int rtn = 0;
 116
 117        rtn = try_module_get(THIS_MODULE);
 118        if (!rtn)
 119                return -ENXIO;
 120
 121        rtn = 0;
 122
 123        if (!capable(CAP_SYS_ADMIN)) {
 124                rtn = -EPERM;
 125                goto done;
 126        }
 127
 128        /*
 129         *  Make sure that the "private_data" field hasn't already been used.
 130         */
 131        if (file->private_data) {
 132                rtn = -EINVAL;
 133                goto done;
 134        }
 135
 136        /*
 137         *  Get the node pointer, and fail if it doesn't exist.
 138         */
 139        nd = PDE_DATA(inode);
 140        if (!nd) {
 141                rtn = -ENXIO;
 142                goto done;
 143        }
 144
 145        file->private_data = (void *) nd;
 146
 147        /*
 148         * Allocate the DPA buffer.
 149         */
 150
 151        if (nd->nd_dpa_buf) {
 152                rtn = -EBUSY;
 153        } else {
 154                nd->nd_dpa_buf = kmalloc(DPA_MAX, GFP_KERNEL);
 155
 156                if (!nd->nd_dpa_buf) {
 157                        rtn = -ENOMEM;
 158                } else {
 159                        nd->nd_dpa_out = 0;
 160                        nd->nd_dpa_in = 0;
 161                        nd->nd_dpa_lbolt = jiffies;
 162                }
 163        }
 164
 165done:
 166
 167        if (rtn)
 168                module_put(THIS_MODULE);
 169        return rtn;
 170}
 171
 172/*
 173 * dgrp_dpa_release -- close the DPA device for a particular PortServer
 174 */
 175static int dgrp_dpa_release(struct inode *inode, struct file *file)
 176{
 177        struct nd_struct *nd;
 178        u8 *buf;
 179        unsigned long lock_flags;
 180
 181        /*
 182         *  Get the node pointer, and quit if it doesn't exist.
 183         */
 184        nd = (struct nd_struct *)(file->private_data);
 185        if (!nd)
 186                goto done;
 187
 188        /*
 189         *  Free the dpa buffer.
 190         */
 191
 192        spin_lock_irqsave(&nd->nd_dpa_lock, lock_flags);
 193
 194        buf = nd->nd_dpa_buf;
 195
 196        nd->nd_dpa_buf = NULL;
 197        nd->nd_dpa_out = nd->nd_dpa_in;
 198
 199        /*
 200         *  Wakeup any thread waiting for buffer space.
 201         */
 202
 203        if (nd->nd_dpa_flag & DPA_WAIT_SPACE) {
 204                nd->nd_dpa_flag &= ~DPA_WAIT_SPACE;
 205                wake_up_interruptible(&nd->nd_dpa_wqueue);
 206        }
 207
 208        spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags);
 209
 210        kfree(buf);
 211
 212done:
 213        module_put(THIS_MODULE);
 214        file->private_data = NULL;
 215        return 0;
 216}
 217
 218/*
 219 * dgrp_dpa_read
 220 *
 221 * Copy data from the monitoring buffer to the user, freeing space
 222 * in the monitoring buffer for more messages
 223 */
 224static ssize_t dgrp_dpa_read(struct file *file, char __user *buf, size_t count,
 225                             loff_t *ppos)
 226{
 227        struct nd_struct *nd;
 228        int n;
 229        int r;
 230        int offset = 0;
 231        int res = 0;
 232        ssize_t rtn;
 233        unsigned long lock_flags;
 234
 235        /*
 236         *  Get the node pointer, and quit if it doesn't exist.
 237         */
 238        nd = (struct nd_struct *)(file->private_data);
 239        if (!nd)
 240                return -ENXIO;
 241
 242        /*
 243         *  Wait for some data to appear in the buffer.
 244         */
 245
 246        spin_lock_irqsave(&nd->nd_dpa_lock, lock_flags);
 247
 248        for (;;) {
 249                n = (nd->nd_dpa_in - nd->nd_dpa_out) & DPA_MASK;
 250
 251                if (n != 0)
 252                        break;
 253
 254                nd->nd_dpa_flag |= DPA_WAIT_DATA;
 255
 256                spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags);
 257
 258                /*
 259                 * Go to sleep waiting until the condition becomes true.
 260                 */
 261                rtn = wait_event_interruptible(nd->nd_dpa_wqueue,
 262                        ((nd->nd_dpa_flag & DPA_WAIT_DATA) == 0));
 263
 264                if (rtn)
 265                        return rtn;
 266
 267                spin_lock_irqsave(&nd->nd_dpa_lock, lock_flags);
 268        }
 269
 270        /*
 271         *  Read whatever is there.
 272         */
 273
 274        if (n > count)
 275                n = count;
 276
 277        res = n;
 278
 279        r = DPA_MAX - nd->nd_dpa_out;
 280
 281        if (r <= n) {
 282
 283                spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags);
 284                rtn = copy_to_user((void __user *)buf,
 285                                   nd->nd_dpa_buf + nd->nd_dpa_out, r);
 286                spin_lock_irqsave(&nd->nd_dpa_lock, lock_flags);
 287
 288                if (rtn) {
 289                        rtn = -EFAULT;
 290                        goto done;
 291                }
 292
 293                nd->nd_dpa_out = 0;
 294                n -= r;
 295                offset = r;
 296        }
 297
 298        spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags);
 299        rtn = copy_to_user((void __user *)buf + offset,
 300                           nd->nd_dpa_buf + nd->nd_dpa_out, n);
 301        spin_lock_irqsave(&nd->nd_dpa_lock, lock_flags);
 302
 303        if (rtn) {
 304                rtn = -EFAULT;
 305                goto done;
 306        }
 307
 308        nd->nd_dpa_out += n;
 309
 310        *ppos += res;
 311
 312        rtn = res;
 313
 314        /*
 315         *  Wakeup any thread waiting for buffer space.
 316         */
 317
 318        n = (nd->nd_dpa_in - nd->nd_dpa_out) & DPA_MASK;
 319
 320        if (nd->nd_dpa_flag & DPA_WAIT_SPACE &&
 321            (DPA_MAX - n) > DPA_HIGH_WATER) {
 322                nd->nd_dpa_flag &= ~DPA_WAIT_SPACE;
 323                wake_up_interruptible(&nd->nd_dpa_wqueue);
 324        }
 325
 326 done:
 327        spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags);
 328        return rtn;
 329}
 330
 331static unsigned int dgrp_dpa_select(struct file *file,
 332                                    struct poll_table_struct *table)
 333{
 334        unsigned int retval = 0;
 335        struct nd_struct *nd = file->private_data;
 336
 337        if (nd->nd_dpa_out != nd->nd_dpa_in)
 338                retval |= POLLIN | POLLRDNORM; /* Conditionally readable */
 339
 340        retval |= POLLOUT | POLLWRNORM;        /* Always writeable */
 341
 342        return retval;
 343}
 344
 345static long dgrp_dpa_ioctl(struct file *file, unsigned int cmd,
 346                           unsigned long arg)
 347{
 348
 349        struct nd_struct  *nd;
 350        struct digi_chan getchan;
 351        struct digi_node getnode;
 352        struct ch_struct *ch;
 353        struct digi_debug setdebug;
 354        struct digi_vpd vpd;
 355        unsigned int port;
 356        void __user *uarg = (void __user *) arg;
 357
 358        nd = file->private_data;
 359
 360        switch (cmd) {
 361        case DIGI_GETCHAN:
 362                if (copy_from_user(&getchan, uarg, sizeof(struct digi_chan)))
 363                        return -EFAULT;
 364
 365                port = getchan.ch_port;
 366
 367                if (port > nd->nd_chan_count)
 368                        return -EINVAL;
 369
 370                ch = nd->nd_chan + port;
 371
 372                getchan.ch_open = (ch->ch_open_count > 0) ? 1 : 0;
 373                getchan.ch_txcount = ch->ch_txcount;
 374                getchan.ch_rxcount = ch->ch_rxcount;
 375                getchan.ch_s_brate = ch->ch_s_brate;
 376                getchan.ch_s_estat = ch->ch_s_elast;
 377                getchan.ch_s_cflag = ch->ch_s_cflag;
 378                getchan.ch_s_iflag = ch->ch_s_iflag;
 379                getchan.ch_s_oflag = ch->ch_s_oflag;
 380                getchan.ch_s_xflag = ch->ch_s_xflag;
 381                getchan.ch_s_mstat = ch->ch_s_mlast;
 382
 383                if (copy_to_user(uarg, &getchan, sizeof(struct digi_chan)))
 384                        return -EFAULT;
 385                break;
 386
 387
 388        case DIGI_GETNODE:
 389                getnode.nd_state = (nd->nd_state & NS_READY) ? 1 : 0;
 390                getnode.nd_chan_count = nd->nd_chan_count;
 391                getnode.nd_tx_byte = nd->nd_tx_byte;
 392                getnode.nd_rx_byte = nd->nd_rx_byte;
 393
 394                memset(&getnode.nd_ps_desc, 0, MAX_DESC_LEN);
 395                strlcpy(getnode.nd_ps_desc, nd->nd_ps_desc, MAX_DESC_LEN);
 396
 397                if (copy_to_user(uarg, &getnode, sizeof(struct digi_node)))
 398                        return -EFAULT;
 399                break;
 400
 401
 402        case DIGI_SETDEBUG:
 403                if (copy_from_user(&setdebug, uarg, sizeof(struct digi_debug)))
 404                        return -EFAULT;
 405
 406                nd->nd_dpa_debug = setdebug.onoff;
 407                nd->nd_dpa_port = setdebug.port;
 408                break;
 409
 410
 411        case DIGI_GETVPD:
 412                memset(&vpd, 0, sizeof(vpd));
 413                if (nd->nd_vpd_len > 0) {
 414                        vpd.vpd_len = nd->nd_vpd_len;
 415                        memcpy(&vpd.vpd_data, &nd->nd_vpd, nd->nd_vpd_len);
 416                } else {
 417                        vpd.vpd_len = 0;
 418                }
 419
 420                if (copy_to_user(uarg, &vpd, sizeof(struct digi_vpd)))
 421                        return -EFAULT;
 422                break;
 423        }
 424
 425        return 0;
 426}
 427
 428/**
 429 * dgrp_dpa() -- send data to the device monitor queue
 430 * @nd: pointer to a node structure
 431 * @buf: buffer of data to copy to the monitoring buffer
 432 * @len: number of bytes to transfer to the buffer
 433 *
 434 * Called by the net device routines to send data to the device
 435 * monitor queue.  If the device monitor buffer is too full to
 436 * accept the data, it waits until the buffer is ready.
 437 */
 438static void dgrp_dpa(struct nd_struct *nd, u8 *buf, int nbuf)
 439{
 440        int n;
 441        int r;
 442        unsigned long lock_flags;
 443
 444        /*
 445         *  Grab DPA lock.
 446         */
 447        spin_lock_irqsave(&nd->nd_dpa_lock, lock_flags);
 448
 449        /*
 450         *  Loop while data remains.
 451         */
 452        while (nbuf > 0 && nd->nd_dpa_buf != NULL) {
 453
 454                n = (nd->nd_dpa_out - nd->nd_dpa_in - 1) & DPA_MASK;
 455
 456                /*
 457                 * Enforce flow control on the DPA device.
 458                 */
 459                if (n < (DPA_MAX - DPA_HIGH_WATER))
 460                        nd->nd_dpa_flag |= DPA_WAIT_SPACE;
 461
 462                /*
 463                 * This should never happen, as the flow control above
 464                 * should have stopped things before they got to this point.
 465                 */
 466                if (n == 0) {
 467                        spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags);
 468                        return;
 469                }
 470
 471                /*
 472                 * Copy as much data as will fit.
 473                 */
 474
 475                if (n > nbuf)
 476                        n = nbuf;
 477
 478                r = DPA_MAX - nd->nd_dpa_in;
 479
 480                if (r <= n) {
 481                        memcpy(nd->nd_dpa_buf + nd->nd_dpa_in, buf, r);
 482
 483                        n -= r;
 484
 485                        nd->nd_dpa_in = 0;
 486
 487                        buf += r;
 488                        nbuf -= r;
 489                }
 490
 491                memcpy(nd->nd_dpa_buf + nd->nd_dpa_in, buf, n);
 492
 493                nd->nd_dpa_in += n;
 494
 495                buf += n;
 496                nbuf -= n;
 497
 498                if (nd->nd_dpa_in >= DPA_MAX)
 499                        pr_info_ratelimited("%s - nd->nd_dpa_in (%i) >= DPA_MAX\n",
 500                                            __func__, nd->nd_dpa_in);
 501
 502                /*
 503                 *  Wakeup any thread waiting for data
 504                 */
 505                if (nd->nd_dpa_flag & DPA_WAIT_DATA) {
 506                        nd->nd_dpa_flag &= ~DPA_WAIT_DATA;
 507                        wake_up_interruptible(&nd->nd_dpa_wqueue);
 508                }
 509        }
 510
 511        /*
 512         *  Release the DPA lock.
 513         */
 514        spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags);
 515}
 516
 517/**
 518 * dgrp_monitor_data() -- builds a DPA data packet
 519 * @nd: pointer to a node structure
 520 * @type: type of message to be logged in the DPA buffer
 521 * @buf: buffer of data to be logged in the DPA buffer
 522 * @size -- number of bytes in the "buf" buffer
 523 */
 524void dgrp_dpa_data(struct nd_struct *nd, int type, u8 *buf, int size)
 525{
 526        u8 header[5];
 527
 528        header[0] = type;
 529
 530        put_unaligned_be32(size, header + 1);
 531
 532        dgrp_dpa(nd, header, sizeof(header));
 533        dgrp_dpa(nd, buf, size);
 534}
 535