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

📄 monreader.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * drivers/s390/char/monreader.c * * Character device driver for reading z/VM *MONITOR service records. * * Copyright (C) 2004 IBM Corporation, IBM Deutschland Entwicklung GmbH. * * Author: Gerald Schaefer <geraldsc@de.ibm.com> */#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/init.h>#include <linux/errno.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/miscdevice.h>#include <linux/ctype.h>#include <linux/spinlock.h>#include <linux/interrupt.h>#include <asm/uaccess.h>#include <asm/ebcdic.h>#include <asm/extmem.h>#include <linux/poll.h>#include "../net/iucv.h"//#define MON_DEBUG			/* Debug messages on/off */#define MON_NAME "monreader"#define P_INFO(x...)	printk(KERN_INFO MON_NAME " info: " x)#define P_ERROR(x...)	printk(KERN_ERR MON_NAME " error: " x)#define P_WARNING(x...)	printk(KERN_WARNING MON_NAME " warning: " x)#ifdef MON_DEBUG#define P_DEBUG(x...)   printk(KERN_DEBUG MON_NAME " debug: " x)#else#define P_DEBUG(x...)   do {} while (0)#endif#define MON_COLLECT_SAMPLE 0x80#define MON_COLLECT_EVENT  0x40#define MON_SERVICE	   "*MONITOR"#define MON_IN_USE	   0x01#define MON_MSGLIM	   255static char mon_dcss_name[9] = "MONDCSS\0";struct mon_msg {	u32 pos;	u32 mca_offset;	iucv_MessagePending local_eib;	char msglim_reached;	char replied_msglim;};struct mon_private {	u16 pathid;	iucv_handle_t iucv_handle;	struct mon_msg *msg_array[MON_MSGLIM];	unsigned int   write_index;	unsigned int   read_index;	atomic_t msglim_count;	atomic_t read_ready;	atomic_t iucv_connected;	atomic_t iucv_severed;};static unsigned long mon_in_use = 0;static unsigned long mon_dcss_start;static unsigned long mon_dcss_end;static DECLARE_WAIT_QUEUE_HEAD(mon_read_wait_queue);static DECLARE_WAIT_QUEUE_HEAD(mon_conn_wait_queue);static u8 iucv_host[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};static u8 user_data_connect[16] = {	/* Version code, must be 0x01 for shared mode */	0x01,	/* what to collect */	MON_COLLECT_SAMPLE | MON_COLLECT_EVENT,	/* DCSS name in EBCDIC, 8 bytes padded with blanks */	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,	0xff, 0xff, 0xff, 0xff, 0xff, 0xff,};static u8 user_data_sever[16] = {	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,};/****************************************************************************** *                             helper functions                               * *****************************************************************************//* * Create the 8 bytes EBCDIC DCSS segment name from * an ASCII name, incl. padding */static inline voiddcss_mkname(char *ascii_name, char *ebcdic_name){	int i;	for (i = 0; i < 8; i++) {		if (ascii_name[i] == '\0')			break;		ebcdic_name[i] = toupper(ascii_name[i]);	};	for (; i < 8; i++)		ebcdic_name[i] = ' ';	ASCEBC(ebcdic_name, 8);}/* * print appropriate error message for segment_load()/segment_type() * return code */static voidmon_segment_warn(int rc, char* seg_name){	switch (rc) {	case -ENOENT:		P_WARNING("cannot load/query segment %s, does not exist\n",			  seg_name);		break;	case -ENOSYS:		P_WARNING("cannot load/query segment %s, not running on VM\n",			  seg_name);		break;	case -EIO:		P_WARNING("cannot load/query segment %s, hardware error\n",			  seg_name);		break;	case -ENOTSUPP:		P_WARNING("cannot load/query segment %s, is a multi-part "			  "segment\n", seg_name);		break;	case -ENOSPC:		P_WARNING("cannot load/query segment %s, overlaps with "			  "storage\n", seg_name);		break;	case -EBUSY:		P_WARNING("cannot load/query segment %s, overlaps with "			  "already loaded dcss\n", seg_name);		break;	case -EPERM:		P_WARNING("cannot load/query segment %s, already loaded in "			  "incompatible mode\n", seg_name);		break;	case -ENOMEM:		P_WARNING("cannot load/query segment %s, out of memory\n",			  seg_name);		break;	case -ERANGE:		P_WARNING("cannot load/query segment %s, exceeds kernel "			  "mapping range\n", seg_name);		break;	default:		P_WARNING("cannot load/query segment %s, return value %i\n",			  seg_name, rc);		break;	}}static inline unsigned longmon_mca_start(struct mon_msg *monmsg){	return monmsg->local_eib.ln1msg1.iprmmsg1_u32;}static inline unsigned longmon_mca_end(struct mon_msg *monmsg){	return monmsg->local_eib.ln1msg2.ipbfln1f;}static inline u8mon_mca_type(struct mon_msg *monmsg, u8 index){	return *((u8 *) mon_mca_start(monmsg) + monmsg->mca_offset + index);}static inline u32mon_mca_size(struct mon_msg *monmsg){	return mon_mca_end(monmsg) - mon_mca_start(monmsg) + 1;}static inline u32mon_rec_start(struct mon_msg *monmsg){	return *((u32 *) (mon_mca_start(monmsg) + monmsg->mca_offset + 4));}static inline u32mon_rec_end(struct mon_msg *monmsg){	return *((u32 *) (mon_mca_start(monmsg) + monmsg->mca_offset + 8));}static inline intmon_check_mca(struct mon_msg *monmsg){	if ((mon_rec_end(monmsg) <= mon_rec_start(monmsg)) ||	    (mon_rec_start(monmsg) < mon_dcss_start) ||	    (mon_rec_end(monmsg) > mon_dcss_end) ||	    (mon_mca_type(monmsg, 0) == 0) ||	    (mon_mca_size(monmsg) % 12 != 0) ||	    (mon_mca_end(monmsg) <= mon_mca_start(monmsg)) ||	    (mon_mca_end(monmsg) > mon_dcss_end) ||	    (mon_mca_start(monmsg) < mon_dcss_start) ||	    ((mon_mca_type(monmsg, 1) == 0) && (mon_mca_type(monmsg, 2) == 0)))	{		P_DEBUG("READ, IGNORED INVALID MCA\n\n");		return -EINVAL;	}	return 0;}static inline intmon_send_reply(struct mon_msg *monmsg, struct mon_private *monpriv){	u8 prmmsg[8];	int rc;	P_DEBUG("read, REPLY: pathid = 0x%04X, msgid = 0x%08X, trgcls = "		"0x%08X\n\n",		monmsg->local_eib.ippathid, monmsg->local_eib.ipmsgid,		monmsg->local_eib.iptrgcls);	rc = iucv_reply_prmmsg(monmsg->local_eib.ippathid,				monmsg->local_eib.ipmsgid,				monmsg->local_eib.iptrgcls,				0, prmmsg);	atomic_dec(&monpriv->msglim_count);	if (likely(!monmsg->msglim_reached)) {		monmsg->pos = 0;		monmsg->mca_offset = 0;		monpriv->read_index = (monpriv->read_index + 1) %				      MON_MSGLIM;		atomic_dec(&monpriv->read_ready);	} else		monmsg->replied_msglim = 1;	if (rc) {		P_ERROR("read, IUCV reply failed with rc = %i\n\n", rc);		return -EIO;	}	return 0;}static inline struct mon_private *mon_alloc_mem(void){	int i,j;	struct mon_private *monpriv;	monpriv = kmalloc(sizeof(struct mon_private), GFP_KERNEL);	if (!monpriv) {		P_ERROR("no memory for monpriv\n");		return NULL;	}	memset(monpriv, 0, sizeof(struct mon_private));	for (i = 0; i < MON_MSGLIM; i++) {		monpriv->msg_array[i] = kmalloc(sizeof(struct mon_msg),						    GFP_KERNEL);		if (!monpriv->msg_array[i]) {			P_ERROR("open, no memory for msg_array\n");			for (j = 0; j < i; j++)				kfree(monpriv->msg_array[j]);			return NULL;		}		memset(monpriv->msg_array[i], 0, sizeof(struct mon_msg));	}	return monpriv;}static inline voidmon_read_debug(struct mon_msg *monmsg, struct mon_private *monpriv){#ifdef MON_DEBUG	u8 msg_type[2], mca_type;	unsigned long records_len;	records_len = mon_rec_end(monmsg) - mon_rec_start(monmsg) + 1;	memcpy(msg_type, &monmsg->local_eib.iptrgcls, 2);	EBCASC(msg_type, 2);	mca_type = mon_mca_type(monmsg, 0);	EBCASC(&mca_type, 1);	P_DEBUG("read, mon_read_index = %i, mon_write_index = %i\n",		monpriv->read_index, monpriv->write_index);	P_DEBUG("read, pathid = 0x%04X, msgid = 0x%08X, trgcls = 0x%08X\n",		monmsg->local_eib.ippathid, monmsg->local_eib.ipmsgid,		monmsg->local_eib.iptrgcls);	P_DEBUG("read, msg_type = '%c%c', mca_type = '%c' / 0x%X / 0x%X\n",		msg_type[0], msg_type[1], mca_type ? mca_type : 'X',		mon_mca_type(monmsg, 1), mon_mca_type(monmsg, 2));	P_DEBUG("read, MCA: start = 0x%lX, end = 0x%lX\n",		mon_mca_start(monmsg), mon_mca_end(monmsg));	P_DEBUG("read, REC: start = 0x%X, end = 0x%X, len = %lu\n\n",		mon_rec_start(monmsg), mon_rec_end(monmsg), records_len);	if (mon_mca_size(monmsg) > 12)		P_DEBUG("READ, MORE THAN ONE MCA\n\n");#endif}static inline voidmon_next_mca(struct mon_msg *monmsg){	if (likely((mon_mca_size(monmsg) - monmsg->mca_offset) == 12))		return;	P_DEBUG("READ, NEXT MCA\n\n");	monmsg->mca_offset += 12;	monmsg->pos = 0;}static inline struct mon_msg *mon_next_message(struct mon_private *monpriv){	struct mon_msg *monmsg;	if (!atomic_read(&monpriv->read_ready))		return NULL;	monmsg = monpriv->msg_array[monpriv->read_index];	if (unlikely(monmsg->replied_msglim)) {		monmsg->replied_msglim = 0;		monmsg->msglim_reached = 0;		monmsg->pos = 0;

⌨️ 快捷键说明

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