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