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

📄 hwc_rw.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *  drivers/s390/char/hwc_rw.c *     driver: reading from and writing to system console on S/390 via HWC * *  S390 version *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation *    Author(s): Martin Peschke <mpeschke@de.ibm.com> * *  * *  *  *  */#include <linux/kernel.h>#include <linux/string.h>#include <linux/errno.h>#include <linux/ctype.h>#include <linux/mm.h>#include <linux/timer.h>#include <linux/bootmem.h>#include <linux/module.h>#include <asm/ebcdic.h>#include <asm/uaccess.h>#include <asm/types.h>#include <asm/bitops.h>#include <asm/setup.h>#include <asm/page.h>#include <asm/s390_ext.h>#include <asm/irq.h>#ifndef MIN#define MIN(a,b) (((a<b) ? a : b))#endifextern void ctrl_alt_del (void);#define HWC_RW_PRINT_HEADER "hwc low level driver: "#define  USE_VM_DETECTION#define  DEFAULT_CASE_DELIMITER '%'#undef DUMP_HWC_INIT_ERROR#undef DUMP_HWC_WRITE_ERROR#undef DUMP_HWC_WRITE_LIST_ERROR#undef DUMP_HWC_READ_ERROR#undef DUMP_HWCB_INPUT#undef BUFFER_STRESS_TESTtypedef struct {	unsigned char *next;	unsigned short int mto_char_sum;	unsigned char mto_number;	unsigned char times_lost;	unsigned short int mto_number_lost;	unsigned long int mto_char_sum_lost;} __attribute__ ((packed)) hwcb_list_t;#define MAX_HWCB_ROOM (PAGE_SIZE - sizeof(hwcb_list_t))#define MAX_MESSAGE_SIZE (MAX_HWCB_ROOM - sizeof(write_hwcb_t))#define BUF_HWCB hwc_data.hwcb_list_tail#define OUT_HWCB hwc_data.hwcb_list_head#define ALL_HWCB_MTO hwc_data.mto_number#define ALL_HWCB_CHAR hwc_data.mto_char_sum#define _LIST(hwcb) ((hwcb_list_t*)(&(hwcb)[PAGE_SIZE-sizeof(hwcb_list_t)]))#define _HWCB_CHAR(hwcb) (_LIST(hwcb)->mto_char_sum)#define _HWCB_MTO(hwcb) (_LIST(hwcb)->mto_number)#define _HWCB_CHAR_LOST(hwcb) (_LIST(hwcb)->mto_char_sum_lost)#define _HWCB_MTO_LOST(hwcb) (_LIST(hwcb)->mto_number_lost)#define _HWCB_TIMES_LOST(hwcb) (_LIST(hwcb)->times_lost)#define _HWCB_NEXT(hwcb) (_LIST(hwcb)->next)#define BUF_HWCB_CHAR _HWCB_CHAR(BUF_HWCB)#define BUF_HWCB_MTO _HWCB_MTO(BUF_HWCB)#define BUF_HWCB_NEXT _HWCB_NEXT(BUF_HWCB)#define OUT_HWCB_CHAR _HWCB_CHAR(OUT_HWCB)#define OUT_HWCB_MTO _HWCB_MTO(OUT_HWCB)#define OUT_HWCB_NEXT _HWCB_NEXT(OUT_HWCB)#define BUF_HWCB_CHAR_LOST _HWCB_CHAR_LOST(BUF_HWCB)#define BUF_HWCB_MTO_LOST _HWCB_MTO_LOST(BUF_HWCB)#define OUT_HWCB_CHAR_LOST _HWCB_CHAR_LOST(OUT_HWCB)#define OUT_HWCB_MTO_LOST _HWCB_MTO_LOST(OUT_HWCB)#define BUF_HWCB_TIMES_LOST _HWCB_TIMES_LOST(BUF_HWCB)#include  "hwc.h"#define __HWC_RW_C__#include "hwc_rw.h"#undef __HWC_RW_C__static unsigned char _obuf[MAX_HWCB_ROOM];static unsigned char _page[PAGE_SIZE] __attribute__ ((aligned (PAGE_SIZE)));typedef unsigned long kmem_pages_t;#define MAX_KMEM_PAGES (sizeof(kmem_pages_t) << 3)#define HWC_WTIMER_RUNS	1#define HWC_FLUSH		2#define HWC_INIT		4#define HWC_BROKEN		8#define HWC_INTERRUPT		16#define HWC_PTIMER_RUNS	32static struct {	hwc_ioctls_t ioctls;	hwc_ioctls_t init_ioctls;	unsigned char *hwcb_list_head;	unsigned char *hwcb_list_tail;	unsigned short int mto_number;	unsigned int mto_char_sum;	unsigned char hwcb_count;	unsigned long kmem_start;	unsigned long kmem_end;	kmem_pages_t kmem_pages;	unsigned char *obuf;	unsigned short int obuf_cursor;	unsigned short int obuf_count;	unsigned short int obuf_start;	unsigned char *page;	u32 current_servc;	unsigned char *current_hwcb;	unsigned char write_nonprio:1;	unsigned char write_prio:1;	unsigned char read_nonprio:1;	unsigned char read_prio:1;	unsigned char read_statechange:1;	unsigned char sig_quiesce:1;	unsigned char flags;	hwc_high_level_calls_t *calls;	hwc_request_t *request;	spinlock_t lock;	struct timer_list write_timer;	struct timer_list poll_timer;} hwc_data ={	{	},	{		8,		    0,		    80,		    1,		    MAX_KMEM_PAGES,		    MAX_KMEM_PAGES,		    0,		    0x6c	},	    NULL,	    NULL,	    0,	    0,	    0,	    0,	    0,	    0,	    _obuf,	    0,	    0,	    0,	    _page,	    0,	    NULL,	    0,	    0,	    0,	    0,	    0,	    0,	    0,	    NULL,	    NULL};static unsigned long cr0 __attribute__ ((aligned (8)));static unsigned long cr0_save __attribute__ ((aligned (8)));static unsigned char psw_mask __attribute__ ((aligned (8)));static ext_int_info_t ext_int_info_hwc;#define DELAYED_WRITE 0#define IMMEDIATE_WRITE 1static signed int do_hwc_write (int from_user, unsigned char *,				unsigned int,				unsigned char);unsigned char hwc_ip_buf[512];static asmlinkage int internal_print (char write_time, char *fmt,...){	va_list args;	int i;	va_start (args, fmt);	i = vsprintf (hwc_ip_buf, fmt, args);	va_end (args);	return do_hwc_write (0, hwc_ip_buf, i, write_time);}int hwc_printk (const char *fmt,...){	va_list args;	int i;	unsigned long flags;	int retval;	spin_lock_irqsave (&hwc_data.lock, flags);	i = vsprintf (hwc_ip_buf, fmt, args);	va_end (args);	retval = do_hwc_write (0, hwc_ip_buf, i, IMMEDIATE_WRITE);	spin_unlock_irqrestore (&hwc_data.lock, flags);	return retval;}#ifdef DUMP_HWCB_INPUTstatic void dump_storage_area (unsigned char *area, unsigned short int count){	unsigned short int index;	ioctl_nl_t old_final_nl;	if (!area || !count)		return;	old_final_nl = hwc_data.ioctls.final_nl;	hwc_data.ioctls.final_nl = 1;	internal_print (DELAYED_WRITE, "\n%8x   ", area);	for (index = 0; index < count; index++) {		if (area[index] <= 0xF)			internal_print (DELAYED_WRITE, "0%x", area[index]);		else			internal_print (DELAYED_WRITE, "%x", area[index]);		if ((index & 0xF) == 0xF)			internal_print (DELAYED_WRITE, "\n%8x   ",					&area[index + 1]);		else if ((index & 3) == 3)			internal_print (DELAYED_WRITE, " ");	}	internal_print (IMMEDIATE_WRITE, "\n");	hwc_data.ioctls.final_nl = old_final_nl;}#endifstatic inline u32 service_call (		     u32 hwc_command_word,		     unsigned char hwcb[]){	unsigned int condition_code = 1;	__asm__ __volatile__ ("L 1, 0(%0) \n\t"			      "LRA 2, 0(%1) \n\t"			      ".long 0xB2200012 \n\t"			      :			      :"a" (&hwc_command_word), "a" (hwcb)			      :"1", "2", "memory");	__asm__ __volatile__ ("IPM %0 \n\t"			      "SRL %0, 28 \n\t"			      :"=r" (condition_code));	return condition_code;}static inline unsigned long hwc_ext_int_param (void){	u32 param;	__asm__ __volatile__ ("L %0,128\n\t"			      :"=r" (param));	return (unsigned long) param;}static int prepare_write_hwcb (void){	write_hwcb_t *hwcb;	if (!BUF_HWCB)		return -ENOMEM;	BUF_HWCB_MTO = 0;	BUF_HWCB_CHAR = 0;	hwcb = (write_hwcb_t *) BUF_HWCB;	memcpy (hwcb, &write_hwcb_template, sizeof (write_hwcb_t));	return 0;}static int sane_write_hwcb (void){	unsigned short int lost_msg;	unsigned int lost_char;	unsigned char lost_hwcb;	unsigned char *bad_addr;	unsigned long page;	int page_nr;	if (!OUT_HWCB)		return -ENOMEM;	if ((unsigned long) OUT_HWCB & 0xFFF) {		bad_addr = OUT_HWCB;#ifdef DUMP_HWC_WRITE_LIST_ERROR		__asm__ ("LHI 1,0xe30\n\t"			 "LRA 2,0(%0) \n\t"			 "J .+0 \n\t"	      :	      :	 "a" (bad_addr)	      :	 "1", "2");#endif		hwc_data.kmem_pages = 0;		if ((unsigned long) BUF_HWCB & 0xFFF) {			lost_hwcb = hwc_data.hwcb_count;			lost_msg = ALL_HWCB_MTO;			lost_char = ALL_HWCB_CHAR;			OUT_HWCB = NULL;			BUF_HWCB = NULL;			ALL_HWCB_MTO = 0;			ALL_HWCB_CHAR = 0;			hwc_data.hwcb_count = 0;		} else {			lost_hwcb = hwc_data.hwcb_count - 1;			lost_msg = ALL_HWCB_MTO - BUF_HWCB_MTO;			lost_char = ALL_HWCB_CHAR - BUF_HWCB_CHAR;			OUT_HWCB = BUF_HWCB;			ALL_HWCB_MTO = BUF_HWCB_MTO;			ALL_HWCB_CHAR = BUF_HWCB_CHAR;			hwc_data.hwcb_count = 1;			page = (unsigned long) BUF_HWCB;			if (page >= hwc_data.kmem_start &&			    page <= hwc_data.kmem_end) {				page_nr = (int)				    ((page - hwc_data.kmem_start) >> 12);				set_bit (page_nr, &hwc_data.kmem_pages);			}		}		internal_print (				       DELAYED_WRITE,				       HWC_RW_PRINT_HEADER		       "found invalid HWCB at address 0x%lx. List corrupted. "			   "Lost %i HWCBs with %i characters within up to %i "			   "messages. Saved %i HWCB with last %i characters i"				       "within up to %i messages.\n",				       (unsigned long) bad_addr,				       lost_hwcb, lost_char, lost_msg,				       hwc_data.hwcb_count,				       ALL_HWCB_CHAR, ALL_HWCB_MTO);	}	return 0;}static int reuse_write_hwcb (void){	int retval;	if (hwc_data.hwcb_count < 2)#ifdef DUMP_HWC_WRITE_LIST_ERROR		__asm__ ("LHI 1,0xe31\n\t"			 "LRA 2,0(%0)\n\t"			 "LRA 3,0(%1)\n\t"			 "J .+0 \n\t"	      :	      :	 "a" (BUF_HWCB), "a" (OUT_HWCB)	      :	 "1", "2", "3");#else		return -EPERM;#endif	if (hwc_data.current_hwcb == OUT_HWCB) {		if (hwc_data.hwcb_count > 2) {			BUF_HWCB_NEXT = OUT_HWCB_NEXT;			BUF_HWCB = OUT_HWCB_NEXT;			OUT_HWCB_NEXT = BUF_HWCB_NEXT;			BUF_HWCB_NEXT = NULL;		}	} else {		BUF_HWCB_NEXT = OUT_HWCB;		BUF_HWCB = OUT_HWCB;		OUT_HWCB = OUT_HWCB_NEXT;		BUF_HWCB_NEXT = NULL;	}	BUF_HWCB_TIMES_LOST += 1;	BUF_HWCB_CHAR_LOST += BUF_HWCB_CHAR;	BUF_HWCB_MTO_LOST += BUF_HWCB_MTO;	ALL_HWCB_MTO -= BUF_HWCB_MTO;	ALL_HWCB_CHAR -= BUF_HWCB_CHAR;	retval = prepare_write_hwcb ();	if (hwc_data.hwcb_count == hwc_data.ioctls.max_hwcb)		internal_print (				       DELAYED_WRITE,				       HWC_RW_PRINT_HEADER				       "reached my own limit of "			    "allowed buffer space for output (%i HWCBs = %li "			  "bytes), skipped content of oldest HWCB %i time(s) "				       "(%i lines = %i characters)\n",				       hwc_data.ioctls.max_hwcb,				       hwc_data.ioctls.max_hwcb * PAGE_SIZE,				       BUF_HWCB_TIMES_LOST,				       BUF_HWCB_MTO_LOST,				       BUF_HWCB_CHAR_LOST);	else		internal_print (				       DELAYED_WRITE,				       HWC_RW_PRINT_HEADER				       "page allocation failed, "			   "could not expand buffer for output (currently in "			     "use: %i HWCBs = %li bytes), skipped content of "			"oldest HWCB %i time(s) (%i lines = %i characters)\n",				       hwc_data.hwcb_count,				       hwc_data.hwcb_count * PAGE_SIZE,				       BUF_HWCB_TIMES_LOST,				       BUF_HWCB_MTO_LOST,				       BUF_HWCB_CHAR_LOST);	return retval;}static int allocate_write_hwcb (void){	unsigned char *page;	int page_nr;	if (hwc_data.hwcb_count == hwc_data.ioctls.max_hwcb)		return -ENOMEM;	page_nr = find_first_zero_bit (&hwc_data.kmem_pages, MAX_KMEM_PAGES);	if (page_nr < hwc_data.ioctls.kmem_hwcb) {		page = (unsigned char *)		    (hwc_data.kmem_start + (page_nr << 12));		set_bit (page_nr, &hwc_data.kmem_pages);	} else		page = (unsigned char *) __get_free_page (GFP_ATOMIC | GFP_DMA);	if (!page)		return -ENOMEM;	if (!OUT_HWCB)		OUT_HWCB = page;	else		BUF_HWCB_NEXT = page;	BUF_HWCB = page;	BUF_HWCB_NEXT = NULL;	hwc_data.hwcb_count++;	prepare_write_hwcb ();	BUF_HWCB_TIMES_LOST = 0;	BUF_HWCB_MTO_LOST = 0;	BUF_HWCB_CHAR_LOST = 0;#ifdef BUFFER_STRESS_TEST	internal_print (			       DELAYED_WRITE,			       "*** " HWC_RW_PRINT_HEADER			    "page #%i at 0x%x for buffering allocated. ***\n",			       hwc_data.hwcb_count, page);#endif	return 0;}static int release_write_hwcb (void){	unsigned long page;	int page_nr;	if (!hwc_data.hwcb_count)		return -ENODATA;	if (hwc_data.hwcb_count == 1) {		prepare_write_hwcb ();		ALL_HWCB_CHAR = 0;		ALL_HWCB_MTO = 0;		BUF_HWCB_TIMES_LOST = 0;		BUF_HWCB_MTO_LOST = 0;		BUF_HWCB_CHAR_LOST = 0;	} else {		page = (unsigned long) OUT_HWCB;		ALL_HWCB_MTO -= OUT_HWCB_MTO;		ALL_HWCB_CHAR -= OUT_HWCB_CHAR;		hwc_data.hwcb_count--;		OUT_HWCB = OUT_HWCB_NEXT;		if (page >= hwc_data.kmem_start &&		    page <= hwc_data.kmem_end) {			/*memset((void *) page, 0, PAGE_SIZE); */			page_nr = (int) ((page - hwc_data.kmem_start) >> 12);			clear_bit (page_nr, &hwc_data.kmem_pages);		} else			free_page (page);#ifdef BUFFER_STRESS_TEST		internal_print (				       DELAYED_WRITE,				       "*** " HWC_RW_PRINT_HEADER			 "page at 0x%x released, %i pages still in use ***\n",				       page, hwc_data.hwcb_count);#endif	}	return 0;}

⌨️ 快捷键说明

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