patch-1.3.5 linux/drivers/scsi/scsi_proc.c
Next file: linux/drivers/scsi/scsicam.c
Previous file: linux/drivers/scsi/scsi_module.c
Back to the patch index
Back to the overall index
- Lines: 315
- Date:
Thu Jun 29 12:37:45 1995
- Orig file:
v1.3.4/linux/drivers/scsi/scsi_proc.c
- Orig date:
Thu Jan 1 02:00:00 1970
diff -u --recursive --new-file v1.3.4/linux/drivers/scsi/scsi_proc.c linux/drivers/scsi/scsi_proc.c
@@ -0,0 +1,314 @@
+/*
+ * linux/drivers/scsi/scsi_proc.c
+ *
+ * The functions in this file provide an interface between
+ * the PROC file system and the SCSI device drivers
+ * It is mainly used for debugging, statistics and to pass
+ * information directly to the lowlevel driver.
+ *
+ * (c) 1995 Michael Neuffer neuffer@goofy.zdv.uni-mainz.de
+ * Version: 0.99.5 last change: 95/06/28
+ *
+ * generic command parser provided by:
+ * Andreas Heilwagen <crashcar@informatik.uni-koblenz.de>
+ */
+
+
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/malloc.h>
+#include <linux/proc_fs.h>
+#include <linux/errno.h>
+#include "../block/blk.h"
+#include "scsi.h"
+#include "hosts.h"
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+extern struct proc_dir_entry scsi_dir[];
+extern struct proc_dir_entry scsi_hba_dir[];
+extern int scsi_proc_info(char *, char **, off_t, int, int, int);
+
+
+int get_hba_index(int ino)
+{
+ Scsi_Host_Template *tpnt = scsi_hosts;
+ struct Scsi_Host *hpnt = scsi_hostlist;
+ uint x = 0;
+
+ while (tpnt) {
+ if (ino == tpnt->low_ino)
+ return(x);
+ x += 3;
+ while (hpnt) {
+ hpnt = hpnt->next;
+ x++;
+ }
+ tpnt = tpnt->next;
+ }
+ return(0);
+}
+
+/* generic_proc_info
+ * Used if the driver currently has no own support for /proc/scsi
+ */
+int generic_proc_info(char *buffer, char **start, off_t offset,
+ int length, int inode, int inout)
+{
+ int len, pos, begin;
+
+ if(inout == TRUE)
+ return(-ENOSYS); /* This is a no-op */
+
+ begin = 0;
+ pos = len = sprintf(buffer,
+ "The driver does not yet support the proc-fs\n");
+ if(pos < offset)
+ {
+ len = 0;
+ begin = pos;
+ }
+
+ *start = buffer + (offset - begin); /* Start of wanted data */
+ len -= (offset - begin);
+ if(len > length)
+ len = length;
+
+ return(len);
+}
+
+/* dispatch_scsi_info is the central dispatcher
+ * It is the interface between the proc-fs and the SCSI subsystem code
+ */
+extern int dispatch_scsi_info(int ino, char *buffer, char **start,
+ off_t offset, int length, int func)
+{
+ struct Scsi_Host *hpnt = scsi_hostlist;
+
+ if(func != 2) {
+ if(ino == PROC_SCSI_SCSI)
+ return(scsi_proc_info(buffer, start, offset, length,
+ hpnt->host_no, func));
+ while(hpnt) {
+ if (ino == (hpnt->host_no + PROC_SCSI_FILE))
+ return(hpnt->hostt->proc_info(buffer, start, offset, length,
+ hpnt->host_no, func));
+ hpnt = hpnt->next;
+ }
+ return(-EBADF);
+ } else
+ return(get_hba_index(ino));
+}
+
+inline uint count_templates(void)
+{
+ Scsi_Host_Template *tpnt = scsi_hosts;
+ uint x = 0;
+
+ while (tpnt) {
+ tpnt = tpnt->next;
+ x++;
+ }
+ return (x);
+}
+
+void build_proc_dir_hba_entries(void)
+{
+ Scsi_Host_Template *tpnt = scsi_hosts;
+ struct Scsi_Host *hpnt = scsi_hostlist;
+ static char names[PROC_SCSI_LAST - PROC_SCSI_FILE][3];
+ uint x, y;
+
+ x = y = 0;
+
+ while (tpnt) {
+ scsi_hba_dir[x].low_ino = tpnt->low_ino;
+ scsi_hba_dir[x].namelen = 1;
+ scsi_hba_dir[x++].name = ".";
+ scsi_hba_dir[x].low_ino = PROC_SCSI;
+ scsi_hba_dir[x].namelen = 2;
+ scsi_hba_dir[x++].name = "..";
+
+ while (hpnt) {
+ if (tpnt == hpnt->hostt) {
+ scsi_hba_dir[x].low_ino = PROC_SCSI_FILE + hpnt->host_no;
+ scsi_hba_dir[x].namelen = sprintf(names[y],"%d",hpnt->host_no);
+ scsi_hba_dir[x].name = names[y];
+ y++;
+ x++;
+ }
+ hpnt = hpnt->next;
+ }
+
+ scsi_hba_dir[x].low_ino = 0;
+ scsi_hba_dir[x].namelen = 0;
+ scsi_hba_dir[x++].name = NULL;
+ tpnt = tpnt->next;
+ }
+}
+
+void build_proc_dir_entries(void)
+{
+ Scsi_Host_Template *tpnt = scsi_hosts;
+
+ uint newnum;
+ uint x;
+
+ newnum = count_templates();
+
+ scsi_dir[0].low_ino = PROC_SCSI;
+ scsi_dir[0].namelen = 1;
+ scsi_dir[0].name = ".";
+ scsi_dir[1].low_ino = PROC_ROOT_INO;
+ scsi_dir[1].namelen = 2;
+ scsi_dir[1].name = "..";
+ scsi_dir[2].low_ino = PROC_SCSI_SCSI;
+ scsi_dir[2].namelen = 4;
+ scsi_dir[2].name = "scsi";
+ for(x = 3; x < newnum + 3; x++, tpnt = tpnt->next) {
+ scsi_dir[x].low_ino = tpnt->low_ino;
+ scsi_dir[x].namelen = strlen(tpnt->procname);
+ scsi_dir[x].name = tpnt->procname;
+ }
+ scsi_dir[x].low_ino = 0;
+ scsi_dir[x].namelen = 0;
+ scsi_dir[x].name = NULL;
+
+ build_proc_dir_hba_entries();
+}
+
+
+/*
+ * parseHandle *parseInit(char *buf, char *cmdList, int cmdNum);
+ * gets a pointer to a null terminated data buffer
+ * and a list of commands with blanks as delimiter
+ * in between.
+ * The commands have to be alphanumerically sorted.
+ * cmdNum has to contain the number of commands.
+ * On success, a pointer to a handle structure
+ * is returned, NULL on failure
+ *
+ * int parseOpt(parseHandle *handle, char **param);
+ * processes the next parameter. On success, the
+ * index of the appropriate command in the cmdList
+ * is returned, starting with zero.
+ * param points to the null terminated parameter string.
+ * On failure, -1 is returned.
+ *
+ * The databuffer buf may only contain pairs of commands
+ * options, separated by blanks:
+ * <Command> <Parameter> [<Command> <Parameter>]*
+ */
+
+typedef struct
+{
+ char *buf, /* command buffer */
+ *cmdList, /* command list */
+ *bufPos, /* actual position */
+ **cmdPos, /* cmdList index */
+ cmdNum; /* cmd number */
+} parseHandle;
+
+
+inline int parseFree (parseHandle *handle) /* free memory */
+{
+ kfree (handle->cmdPos);
+ kfree (handle);
+
+ return(-1);
+}
+
+
+parseHandle *parseInit(char *buf, char *cmdList, int cmdNum)
+{
+ char *ptr; /* temp pointer */
+ parseHandle *handle; /* new handle */
+
+ if (!buf || !cmdList) /* bad input ? */
+ return(NULL);
+ if ((handle = (parseHandle*) kmalloc(sizeof(parseHandle), 1)) == 0)
+ return(NULL); /* out of memory */
+ if ((handle->cmdPos = (char**) kmalloc(sizeof(int), cmdNum)) == 0) {
+ kfree(handle);
+ return(NULL); /* out of memory */
+ }
+
+ handle->buf = handle->bufPos = buf; /* init handle */
+ handle->cmdList = cmdList;
+ handle->cmdNum = cmdNum;
+
+ handle->cmdPos[cmdNum = 0] = cmdList;
+ for (ptr = cmdList; *ptr; ptr++) { /* scan command string */
+ if(*ptr == ' ') { /* and insert zeroes */
+ *ptr++ = 0;
+ handle->cmdPos[++cmdNum] = ptr++;
+ }
+ }
+ return(handle);
+}
+
+
+int parseOpt(parseHandle *handle, char **param)
+{
+ int cmdIndex = 0,
+ cmdLen = 0;
+ char *startPos;
+
+ if (!handle) /* invalid handle */
+ return(parseFree(handle));
+ /* skip spaces */
+ for (; *(handle->bufPos) && *(handle->bufPos) == ' '; handle->bufPos++);
+ if (!*(handle->bufPos))
+ return(parseFree(handle)); /* end of data */
+
+ startPos = handle->bufPos; /* store cmd start */
+ for (; handle->cmdPos[cmdIndex][cmdLen] && *(handle->bufPos); handle->bufPos++)
+ { /* no string end? */
+ for (;;)
+ {
+ if (*(handle->bufPos) == handle->cmdPos[cmdIndex][cmdLen])
+ break; /* char matches ? */
+ else
+ if (memcmp(startPos, (char*)(handle->cmdPos[++cmdIndex]), cmdLen))
+ return(parseFree(handle)); /* unknown command */
+
+ if (cmdIndex >= handle->cmdNum)
+ return(parseFree(handle)); /* unknown command */
+ }
+
+ cmdLen++; /* next char */
+ }
+
+ /* Get param. First skip all blanks, then insert zero after param */
+
+ for (; *(handle->bufPos) && *(handle->bufPos) == ' '; handle->bufPos++);
+ *param = handle->bufPos;
+
+ for (; *(handle->bufPos) && *(handle->bufPos) != ' '; handle->bufPos++);
+ *(handle->bufPos++) = 0;
+
+ return(cmdIndex);
+}
+
+
+/*
+ * Overrides for Emacs so that we get a uniform tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 4
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this