hysdn_procconf.c revision d76b0d9b2d87cfc95686e148767cbf7d0e22bdc0
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* $Id: hysdn_procconf.c,v 1.8.6.4 2001/09/23 22:24:54 kai Exp $ 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Linux driver for HYSDN cards, /proc/net filesystem dir and conf functions. 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright 1999 by Werner Cornelius (werner@titro.de) 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This software may be used and distributed according to the terms 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of the GNU General Public License, incorporated herein by reference. 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/poll.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/proc_fs.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/smp_lock.h> 19457c4cbc5a3dde259d2a1f15d5f9785290397267Eric W. Biederman#include <net/net_namespace.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "hysdn_defs.h" 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *hysdn_procconf_revision = "$Revision: 1.8.6.4 $"; 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define INFO_OUT_LEN 80 /* length of info line including lf */ 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************/ 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* defines and data structure for conf write operations */ 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************/ 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CONF_STATE_DETECT 0 /* waiting for detect */ 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CONF_STATE_CONF 1 /* writing config data */ 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CONF_STATE_POF 2 /* writing pof data */ 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CONF_LINE_LEN 255 /* 255 chars max */ 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct conf_writedata { 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_card *card; /* card the device is connected to */ 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int buf_size; /* actual number of bytes in the buffer */ 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int needed_size; /* needed size when reading pof */ 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int state; /* actual interface states from above constants */ 40c721bccece2b3abca4f7b0b95108e68b78445cecAndrew Morton unsigned char conf_line[CONF_LINE_LEN]; /* buffered conf line */ 41c721bccece2b3abca4f7b0b95108e68b78445cecAndrew Morton unsigned short channel; /* active channel number */ 42c721bccece2b3abca4f7b0b95108e68b78445cecAndrew Morton unsigned char *pof_buffer; /* buffer when writing pof */ 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***********************************************************************/ 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* process_line parses one config line and transfers it to the card if */ 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* necessary. */ 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* if the return value is negative an error occurred. */ 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***********************************************************************/ 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsprocess_line(struct conf_writedata *cnf) 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 53c721bccece2b3abca4f7b0b95108e68b78445cecAndrew Morton unsigned char *cp = cnf->conf_line; 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cnf->card->debug_flags & LOG_CNF_LINE) 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_addlog(cnf->card, "conf line: %s", cp); 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*cp == '-') { /* option */ 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cp++; /* point to option char */ 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*cp++ != 'c') 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); /* option unknown or used */ 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = 0; /* start value for channel */ 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while ((*cp <= '9') && (*cp >= '0')) 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = i * 10 + *cp++ - '0'; /* get decimal number */ 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i > 65535) { 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cnf->card->debug_flags & LOG_CNF_MISC) 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_addlog(cnf->card, "conf channel invalid %d", i); 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-ERR_INV_CHAN); /* invalid channel */ 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->channel = i & 0xFFFF; /* set new channel number */ 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); /* success */ 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } /* option */ 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*cp == '*') { /* line to send */ 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cnf->card->debug_flags & LOG_CNF_DATA) 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_addlog(cnf->card, "conf chan=%d %s", cnf->channel, cp); 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (hysdn_tx_cfgline(cnf->card, cnf->conf_line + 1, 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->channel)); /* send the line without * */ 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } /* line to send */ 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* process_line */ 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***********************************/ 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* conf file operations and tables */ 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***********************************/ 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/****************************************************/ 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* write conf file -> boot or send cfg line to card */ 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/****************************************************/ 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldshysdn_conf_write(struct file *file, const char __user *buf, size_t count, loff_t * off) 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct conf_writedata *cnf; 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 96c721bccece2b3abca4f7b0b95108e68b78445cecAndrew Morton unsigned char ch, *cp; 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!count) 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); /* nothing to handle */ 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(cnf = file->private_data)) 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-EFAULT); /* should never happen */ 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cnf->state == CONF_STATE_DETECT) { /* auto detect cnf or pof data */ 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&ch, buf, 1)) /* get first char for detect */ 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-EFAULT); 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch == 0x1A) { 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* we detected a pof file */ 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((cnf->needed_size = pof_write_open(cnf->card, &cnf->pof_buffer)) <= 0) 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (cnf->needed_size); /* an error occurred -> exit */ 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->buf_size = 0; /* buffer is empty */ 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->state = CONF_STATE_POF; /* new state */ 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* conf data has been detected */ 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->buf_size = 0; /* buffer is empty */ 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->state = CONF_STATE_CONF; /* requested conf data write */ 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cnf->card->state != CARD_STATE_RUN) 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-ERR_NOT_BOOTED); 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->conf_line[CONF_LINE_LEN - 1] = 0; /* limit string length */ 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->channel = 4098; /* default channel for output */ 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } /* state was auto detect */ 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cnf->state == CONF_STATE_POF) { /* pof write active */ 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = cnf->needed_size - cnf->buf_size; /* bytes still missing for write */ 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i <= 0) 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-EINVAL); /* size error handling pof */ 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i < count) 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = i; /* limit requested number of bytes */ 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(cnf->pof_buffer + cnf->buf_size, buf, count)) 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-EFAULT); /* error while copying */ 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->buf_size += count; 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cnf->needed_size == cnf->buf_size) { 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->needed_size = pof_write_buffer(cnf->card, cnf->buf_size); /* write data */ 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cnf->needed_size <= 0) { 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->card->state = CARD_STATE_BOOTERR; /* show boot error */ 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (cnf->needed_size); /* an error occurred */ 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->buf_size = 0; /* buffer is empty again */ 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* pof write active */ 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { /* conf write active */ 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cnf->card->state != CARD_STATE_RUN) { 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cnf->card->debug_flags & LOG_CNF_MISC) 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_addlog(cnf->card, "cnf write denied -> not booted"); 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-ERR_NOT_BOOTED); 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = (CONF_LINE_LEN - 1) - cnf->buf_size; /* bytes available in buffer */ 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i > 0) { 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* copy remaining bytes into buffer */ 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count > i) 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = i; /* limit transfer */ 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(cnf->conf_line + cnf->buf_size, buf, count)) 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-EFAULT); /* error while copying */ 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = count; /* number of chars in buffer */ 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cp = cnf->conf_line + cnf->buf_size; 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (i) { 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* search for end of line */ 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((*cp < ' ') && (*cp != 9)) 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; /* end of line found */ 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cp++; 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i--; 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } /* search for end of line */ 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i) { 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* delimiter found */ 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *cp++ = 0; /* string termination */ 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count -= (i - 1); /* subtract remaining bytes from count */ 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while ((i) && (*cp < ' ') && (*cp != 9)) { 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i--; /* discard next char */ 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count++; /* mark as read */ 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cp++; /* next char */ 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->buf_size = 0; /* buffer is empty after transfer */ 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((i = process_line(cnf)) < 0) /* handle the line */ 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = i; /* return the error */ 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* delimiter found */ 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->buf_size += count; /* add chars to string */ 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cnf->buf_size >= CONF_LINE_LEN - 1) { 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cnf->card->debug_flags & LOG_CNF_MISC) 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_addlog(cnf->card, "cnf line too long %d chars pos %d", cnf->buf_size, count); 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-ERR_CONF_LONG); 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } /* not delimited */ 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* copy remaining bytes into buffer */ 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cnf->card->debug_flags & LOG_CNF_MISC) 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_addlog(cnf->card, "cnf line too long"); 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-ERR_CONF_LONG); 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } /* conf write active */ 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (count); 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* hysdn_conf_write */ 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*******************************************/ 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* read conf file -> output card info data */ 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*******************************************/ 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t 210ea23ec26727b4df97b4965715f0519b6ddc0aa4bAkinobu Mitahysdn_conf_read(struct file *file, char __user *buf, size_t count, loff_t *off) 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *cp; 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 214ea23ec26727b4df97b4965715f0519b6ddc0aa4bAkinobu Mita if (!(file->f_mode & FMODE_READ)) 215ea23ec26727b4df97b4965715f0519b6ddc0aa4bAkinobu Mita return -EPERM; /* no permission to read */ 216ea23ec26727b4df97b4965715f0519b6ddc0aa4bAkinobu Mita 217ea23ec26727b4df97b4965715f0519b6ddc0aa4bAkinobu Mita if (!(cp = file->private_data)) 218ea23ec26727b4df97b4965715f0519b6ddc0aa4bAkinobu Mita return -EFAULT; /* should never happen */ 219ea23ec26727b4df97b4965715f0519b6ddc0aa4bAkinobu Mita 220ea23ec26727b4df97b4965715f0519b6ddc0aa4bAkinobu Mita return simple_read_from_buffer(buf, count, off, cp, strlen(cp)); 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* hysdn_conf_read */ 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************/ 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* open conf file */ 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************/ 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldshysdn_conf_open(struct inode *ino, struct file *filep) 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_card *card; 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct proc_dir_entry *pd; 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct conf_writedata *cnf; 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *cp, *tmp; 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* now search the addressed card */ 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_kernel(); 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card = card_root; 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (card) { 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pd = card->procconf; 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pd == PDE(ino)) 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card = card->next; /* search next entry */ 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!card) { 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unlock_kernel(); 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-ENODEV); /* device is unknown/invalid */ 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL)) 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_addlog(card, "config open for uid=%d gid=%d mode=0x%x", 249d76b0d9b2d87cfc95686e148767cbf7d0e22bdc0David Howells filep->f_cred->fsuid, filep->f_cred->fsgid, 250d76b0d9b2d87cfc95686e148767cbf7d0e22bdc0David Howells filep->f_mode); 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) { 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* write only access -> write boot file or conf line */ 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(cnf = kmalloc(sizeof(struct conf_writedata), GFP_KERNEL))) { 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unlock_kernel(); 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-EFAULT); 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->card = card; 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->buf_size = 0; /* nothing buffered */ 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->state = CONF_STATE_DETECT; /* start auto detect */ 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds filep->private_data = cnf; 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) { 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* read access -> output card info data */ 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2675cbded585d129d0226cb48ac4202b253c781be26Robert P. J. Day if (!(tmp = kmalloc(INFO_OUT_LEN * 2 + 2, GFP_KERNEL))) { 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unlock_kernel(); 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-EFAULT); /* out of memory */ 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds filep->private_data = tmp; /* start of string */ 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* first output a headline */ 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(tmp, "id bus slot type irq iobase dp-mem b-chans fax-chans state device"); 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cp = tmp; /* start of string */ 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (*cp) 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cp++; 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (((cp - tmp) % (INFO_OUT_LEN + 1)) != INFO_OUT_LEN) 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *cp++ = ' '; 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *cp++ = '\n'; 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* and now the data */ 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(cp, "%d %3d %4d %4d %3d 0x%04x 0x%08lx %7d %9d %3d %s", 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card->myid, 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card->bus, 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PCI_SLOT(card->devfn), 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card->brdtype, 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card->irq, 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card->iobase, 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card->membase, 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card->bchans, 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card->faxchans, 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card->state, 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_net_getname(card)); 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (*cp) 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cp++; 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (((cp - tmp) % (INFO_OUT_LEN + 1)) != INFO_OUT_LEN) 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *cp++ = ' '; 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *cp++ = '\n'; 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *cp = 0; /* end of string */ 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { /* simultaneous read/write access forbidden ! */ 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unlock_kernel(); 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-EPERM); /* no permission this time */ 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unlock_kernel(); 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return nonseekable_open(ino, filep); 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* hysdn_conf_open */ 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***************************/ 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* close a config file. */ 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***************************/ 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldshysdn_conf_close(struct inode *ino, struct file *filep) 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_card *card; 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct conf_writedata *cnf; 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct proc_dir_entry *pd; 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_kernel(); 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* search the addressed card */ 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card = card_root; 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (card) { 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pd = card->procconf; 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pd == PDE(ino)) 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card = card->next; /* search next entry */ 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!card) { 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unlock_kernel(); 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-ENODEV); /* device is unknown/invalid */ 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL)) 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_addlog(card, "config close for uid=%d gid=%d mode=0x%x", 335d76b0d9b2d87cfc95686e148767cbf7d0e22bdc0David Howells filep->f_cred->fsuid, filep->f_cred->fsgid, 336d76b0d9b2d87cfc95686e148767cbf7d0e22bdc0David Howells filep->f_mode); 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) { 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* write only access -> write boot file or conf line */ 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (filep->private_data) { 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf = filep->private_data; 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cnf->state == CONF_STATE_POF) 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = pof_write_close(cnf->card); /* close the pof write */ 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(filep->private_data); /* free allocated memory for buffer */ 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } /* handle write private data */ 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) { 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* read access -> output card info data */ 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3513c7208f253571ee5f157b98f0e315b5172afe092Jesper Juhl kfree(filep->private_data); /* release memory */ 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unlock_kernel(); 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (retval); 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* hysdn_conf_close */ 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************************/ 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* table for conf filesystem functions defined above. */ 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************************/ 3602b8693c0617e972fc0b2fd1ebf8de97e15b656c3Arjan van de Venstatic const struct file_operations conf_fops = 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 362ac41cfd19bf77424519b962f8205ede51fceaac6Denis V. Lunev .owner = THIS_MODULE, 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .llseek = no_llseek, 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .read = hysdn_conf_read, 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .write = hysdn_conf_write, 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .open = hysdn_conf_open, 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .release = hysdn_conf_close, 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************/ 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* hysdn subdir in /proc/net */ 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************/ 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct proc_dir_entry *hysdn_proc_entry = NULL; 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*******************************************************************************/ 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* hysdn_procconf_init is called when the module is loaded and after the cards */ 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* have been detected. The needed proc dir and card config files are created. */ 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The log init is called at last. */ 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*******************************************************************************/ 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldshysdn_procconf_init(void) 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_card *card; 384c721bccece2b3abca4f7b0b95108e68b78445cecAndrew Morton unsigned char conf_name[20]; 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 386457c4cbc5a3dde259d2a1f15d5f9785290397267Eric W. Biederman hysdn_proc_entry = proc_mkdir(PROC_SUBDIR_NAME, init_net.proc_net); 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!hysdn_proc_entry) { 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "HYSDN: unable to create hysdn subdir\n"); 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-1); 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card = card_root; /* point to first card */ 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (card) { 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(conf_name, "%s%d", PROC_CONF_BASENAME, card->myid); 395ac41cfd19bf77424519b962f8205ede51fceaac6Denis V. Lunev if ((card->procconf = (void *) proc_create(conf_name, 396ac41cfd19bf77424519b962f8205ede51fceaac6Denis V. Lunev S_IFREG | S_IRUGO | S_IWUSR, 3975045790589bd426b5d515d78fa71f0fc92dd4e83Ingo Molnar hysdn_proc_entry, 3985045790589bd426b5d515d78fa71f0fc92dd4e83Ingo Molnar &conf_fops)) != NULL) { 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_proclog_init(card); /* init the log file entry */ 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card = card->next; /* next entry */ 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_NOTICE "HYSDN: procfs Rev. %s initialised\n", hysdn_getrev(hysdn_procconf_revision)); 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* hysdn_procconf_init */ 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*************************************************************************************/ 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* hysdn_procconf_release is called when the module is unloaded and before the cards */ 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* resources are released. The module counter is assumed to be 0 ! */ 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*************************************************************************************/ 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldshysdn_procconf_release(void) 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_card *card; 416c721bccece2b3abca4f7b0b95108e68b78445cecAndrew Morton unsigned char conf_name[20]; 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card = card_root; /* start with first card */ 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (card) { 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(conf_name, "%s%d", PROC_CONF_BASENAME, card->myid); 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (card->procconf) 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds remove_proc_entry(conf_name, hysdn_proc_entry); 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_proclog_release(card); /* init the log file entry */ 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card = card->next; /* point to next card */ 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 430457c4cbc5a3dde259d2a1f15d5f9785290397267Eric W. Biederman remove_proc_entry(PROC_SUBDIR_NAME, init_net.proc_net); 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 432