⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scsi_proc.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
字号:
/* * 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.8   last change: 95/09/13 *  * generic command parser provided by:  * Andreas Heilwagen <crashcar@informatik.uni-koblenz.de> * * generic_proc_info() support of xxxx_info() by: * Michael A. Griffith <grif@acm.org> */#include <linux/config.h>	/* for CONFIG_PROC_FS */#define __NO_VERSION__#include <linux/module.h>#include <linux/string.h>#include <linux/mm.h>#include <linux/malloc.h>#include <linux/proc_fs.h>#include <linux/errno.h>#include <linux/stat.h>#include <linux/blk.h>#include <asm/uaccess.h>#include "scsi.h"#include "hosts.h"#ifndef TRUE#define TRUE  1#define FALSE 0#endif#ifdef CONFIG_PROC_FS/* 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, 		      const char *(*info) (struct Scsi_Host *),		      struct Scsi_Host *sh){	int len, pos, begin;	begin = 0;	if (info && sh) {		pos = len = sprintf(buffer, "%s\n", info(sh));	} else {		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 */static int proc_scsi_read(char *buffer, char **start, off_t offset,	int length, int *eof, void *data){	struct Scsi_Host *hpnt = data;	int n;	if (hpnt->hostt->proc_info == NULL)		n = generic_proc_info(buffer, start, offset, length,				      hpnt->hostt->info, hpnt);	else		n = (hpnt->hostt->proc_info(buffer, start, offset,					   length, hpnt->host_no, 0));	*eof = (n<length);	return n;}#define PROC_BLOCK_SIZE (3*1024)     /* 4K page size, but our output routines 				      * use some slack for overruns 				      */static int proc_scsi_write(struct file * file, const char * buf,                           unsigned long count, void *data){	struct Scsi_Host *hpnt = data;	ssize_t ret = 0;	char * page;	char *start;    	if (count > PROC_BLOCK_SIZE)		return -EOVERFLOW;	if (!(page = (char *) __get_free_page(GFP_KERNEL)))		return -ENOMEM;	copy_from_user(page, buf, count);	if (hpnt->hostt->proc_info == NULL)		ret = -ENOSYS;	else		ret = hpnt->hostt->proc_info(page, &start, 0, count,						hpnt->host_no, 1);	free_page((ulong) page);	return(ret);}void build_proc_dir_entries(Scsi_Host_Template * tpnt){	struct Scsi_Host *hpnt;	char name[10];	/* see scsi_unregister_host() */	tpnt->proc_dir = proc_mkdir(tpnt->proc_name, proc_scsi);	tpnt->proc_dir->owner = tpnt->module;	hpnt = scsi_hostlist;	while (hpnt) {		if (tpnt == hpnt->hostt) {			struct proc_dir_entry *p;			sprintf(name,"%d",hpnt->host_no);			p = create_proc_read_entry(name,					S_IFREG | S_IRUGO | S_IWUSR,					tpnt->proc_dir,					proc_scsi_read,					(void *)hpnt);			if (!p)				panic("Not enough memory to register SCSI HBA in /proc/scsi !\n");			p->write_proc=proc_scsi_write;			p->owner = tpnt->module;		}		hpnt = hpnt->next;	}}/* *  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;	handle = (parseHandle *) kmalloc(sizeof(parseHandle), GFP_KERNEL);	if (!handle)		return NULL;	/* out of memory   */	handle->cmdPos = (char **) kmalloc(sizeof(int) * cmdNum, GFP_KERNEL);	if (!handle->cmdPos) {		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);}void proc_print_scsidevice(Scsi_Device * scd, char *buffer, int *size, int len){	int x, y = *size;	extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE];	y = sprintf(buffer + len,	     "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n  Vendor: ",		    scd->host->host_no, scd->channel, scd->id, scd->lun);	for (x = 0; x < 8; x++) {		if (scd->vendor[x] >= 0x20)			y += sprintf(buffer + len + y, "%c", scd->vendor[x]);		else			y += sprintf(buffer + len + y, " ");	}	y += sprintf(buffer + len + y, " Model: ");	for (x = 0; x < 16; x++) {		if (scd->model[x] >= 0x20)			y += sprintf(buffer + len + y, "%c", scd->model[x]);		else			y += sprintf(buffer + len + y, " ");	}	y += sprintf(buffer + len + y, " Rev: ");	for (x = 0; x < 4; x++) {		if (scd->rev[x] >= 0x20)			y += sprintf(buffer + len + y, "%c", scd->rev[x]);		else			y += sprintf(buffer + len + y, " ");	}	y += sprintf(buffer + len + y, "\n");	y += sprintf(buffer + len + y, "  Type:   %s ",		     scd->type < MAX_SCSI_DEVICE_CODE ?	       scsi_device_types[(int) scd->type] : "Unknown          ");	y += sprintf(buffer + len + y, "               ANSI"		     " SCSI revision: %02x", (scd->scsi_level - 1) ? scd->scsi_level - 1 : 1);	if (scd->scsi_level == 2)		y += sprintf(buffer + len + y, " CCS\n");	else		y += sprintf(buffer + len + y, "\n");	*size = y;	return;}#else				/* if !CONFIG_PROC_FS */void proc_print_scsidevice(Scsi_Device * scd, char *buffer, int *size, int len){}#endif				/* CONFIG_PROC_FS *//* * 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: */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -