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

📄 hwc_rw.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 3 页
字号:
	int retval = 0;	subvec = start;	while (((void *) subvec) < end) {		subvec = find_gds_subvector (					 subvec, end, GDS_KEY_SelfDefTextMsg);		if (!subvec)			break;		subvec_data = (gds_subvector_t *)		    (((unsigned long) subvec) +		     sizeof (gds_subvector_t));		subvec_end = (void *)		    (((unsigned long) subvec) + subvec->length);		retval += eval_selfdeftextmsg (subvec_data, subvec_end);		subvec = (gds_subvector_t *) subvec_end;	}	return retval;}inline static int eval_cpmsu (gds_vector_t * start, void *end){	gds_vector_t *vec;	gds_subvector_t *vec_data;	void *vec_end;	int retval = 0;	vec = start;	while (((void *) vec) < end) {		vec = find_gds_vector (vec, end, GDS_ID_TextCmd);		if (!vec)			break;		vec_data = (gds_subvector_t *)		    (((unsigned long) vec) + sizeof (gds_vector_t));		vec_end = (void *) (((unsigned long) vec) + vec->length);		retval += eval_textcmd (vec_data, vec_end);		vec = (gds_vector_t *) vec_end;	}	return retval;}inline static int eval_mdsmu (gds_vector_t * start, void *end){	gds_vector_t *vec;	gds_vector_t *vec_data;	void *vec_end;	int retval = 0;	vec = find_gds_vector (start, end, GDS_ID_CPMSU);	if (vec) {		vec_data = (gds_vector_t *)		    (((unsigned long) vec) + sizeof (gds_vector_t));		vec_end = (void *) (((unsigned long) vec) + vec->length);		retval = eval_cpmsu (vec_data, vec_end);	}	return retval;}inline static int eval_evbuf (gds_vector_t * start, void *end){	gds_vector_t *vec;	gds_vector_t *vec_data;	void *vec_end;	int retval = 0;	vec = find_gds_vector (start, end, GDS_ID_MDSMU);	if (vec) {		vec_data = (gds_vector_t *)		    (((unsigned long) vec) + sizeof (gds_vector_t));		vec_end = (void *) (((unsigned long) vec) + vec->length);		retval = eval_mdsmu (vec_data, vec_end);	}	return retval;}static int process_evbufs (void *start, void *end){	int retval = 0;	evbuf_t *evbuf;	void *evbuf_end;	gds_vector_t *evbuf_data;	evbuf = (evbuf_t *) start;	while (((void *) evbuf) < end) {		evbuf_data = (gds_vector_t *)		    (((unsigned long) evbuf) + sizeof (evbuf_t));		evbuf_end = (void *) (((unsigned long) evbuf) + evbuf->length);		switch (evbuf->type) {		case ET_OpCmd:		case ET_CntlProgOpCmd:		case ET_PMsgCmd:#ifdef DUMP_HWCB_INPUT			internal_print (					       DELAYED_WRITE,					       HWC_RW_PRINT_HEADER					       "event buffer "					   "at 0x%x up to 0x%x, length: %d\n",					       (unsigned long) evbuf,					       (unsigned long) (evbuf_end - 1),					       evbuf->length);			dump_storage_area ((void *) evbuf, evbuf->length);#endif			retval += eval_evbuf (evbuf_data, evbuf_end);			break;		case ET_StateChange:			retval = -ENOSYS;			break;		default:			printk (				       KERN_WARNING				       HWC_RW_PRINT_HEADER				       "unconditional read: "				       "unknown event buffer found, "				       "type 0x%x",				       evbuf->type);			retval = -ENOSYS;		}		evbuf = (evbuf_t *) evbuf_end;	}	return retval;}static int unconditional_read_1 (void){	unsigned short int condition_code;	read_hwcb_t *hwcb = (read_hwcb_t *) hwc_data.page;	int retval;	if ((!hwc_data.read_prio) && (!hwc_data.read_nonprio))		return -EOPNOTSUPP;	if (hwc_data.current_servc)		return -EBUSY;	memset (hwcb, 0x00, PAGE_SIZE);	memcpy (hwcb, &read_hwcb_template, sizeof (read_hwcb_t));	condition_code = service_call (HWC_CMDW_READDATA, hwc_data.page);#ifdef DUMP_HWC_READ_ERROR	if (condition_code == HWC_NOT_OPERATIONAL)		__asm__ ("LHI 1,0xe40\n\t"			 "L 2,0(0,%0)\n\t"			 "LRA 3,0(0,%1)\n\t"			 "J .+0 \n\t"	      :	      :	 "a" (&condition_code), "a" (hwc_data.page)	      :	 "1", "2", "3");#endif	switch (condition_code) {	case HWC_COMMAND_INITIATED:		hwc_data.current_servc = HWC_CMDW_READDATA;		hwc_data.current_hwcb = hwc_data.page;		retval = condition_code;		break;	case HWC_BUSY:		retval = -EBUSY;		break;	default:		retval = -EIO;	}	return retval;}static int unconditional_read_2 (void){	read_hwcb_t *hwcb = (read_hwcb_t *) hwc_data.page;#ifdef DUMP_HWC_READ_ERROR	if ((hwcb->response_code != 0x0020) &&	    (hwcb->response_code != 0x0220) &&	    (hwcb->response_code != 0x60F0) &&	    (hwcb->response_code != 0x62F0))		__asm__ ("LHI 1,0xe41\n\t"			 "LRA 2,0(0,%0)\n\t"			 "L 3,0(0,%1)\n\t"			 "J .+0\n\t"	      :	      :	 "a" (hwc_data.page), "a" (&(hwcb->response_code))	      :	 "1", "2", "3");#endif	hwc_data.current_servc = 0;	hwc_data.current_hwcb = NULL;	switch (hwcb->response_code) {	case 0x0020:	case 0x0220:		return process_evbufs (		     (void *) (((unsigned long) hwcb) + sizeof (read_hwcb_t)),			    (void *) (((unsigned long) hwcb) + hwcb->length));	case 0x60F0:	case 0x62F0:		return 0;	case 0x0100:		internal_print (				       IMMEDIATE_WRITE,				       HWC_RW_PRINT_HEADER			 "unconditional read: HWCB boundary violation - this "			 "must not occur in a correct driver, please contact "				       "author\n");		return -EIO;	case 0x0300:		internal_print (				       IMMEDIATE_WRITE,				       HWC_RW_PRINT_HEADER				       "unconditional read: "			"insufficient HWCB length - this must not occur in a "				   "correct driver, please contact author\n");		return -EIO;	case 0x01F0:		internal_print (				       IMMEDIATE_WRITE,				       HWC_RW_PRINT_HEADER				       "unconditional read: "			 "invalid command - this must not occur in a correct "				       "driver, please contact author\n");		return -EIO;	case 0x40F0:		internal_print (				       IMMEDIATE_WRITE,				       HWC_RW_PRINT_HEADER			   "unconditional read: invalid function code - this "			 "must not occur in a correct driver, please contact "				       "author\n");		return -EIO;	case 0x70F0:		internal_print (				       IMMEDIATE_WRITE,				       HWC_RW_PRINT_HEADER			  "unconditional read: invalid selection mask - this "			 "must not occur in a correct driver, please contact "				       "author\n");		return -EIO;	case 0x0040:		internal_print (				       IMMEDIATE_WRITE,				       HWC_RW_PRINT_HEADER			    "unconditional read: HWC equipment check - don't "				       "know how to handle this case\n");		return -EIO;	default:		internal_print (				       IMMEDIATE_WRITE,				       HWC_RW_PRINT_HEADER			"unconditional read: invalid response code %x - this "			 "must not occur in a correct driver, please contact "				       "author\n",				       hwcb->response_code);		return -EIO;	}}static int write_event_mask_1 (void){	unsigned int condition_code;	int retval;	memcpy (hwc_data.page, &init_hwcb_template, sizeof (init_hwcb_t));	condition_code = service_call (HWC_CMDW_WRITEMASK, hwc_data.page);#ifdef DUMP_HWC_INIT_ERROR	if (condition_code != HWC_COMMAND_INITIATED)		__asm__ ("LHI 1,0xe10\n\t"			 "L 2,0(0,%0)\n\t"			 "LRA 3,0(0,%1)\n\t"			 "J .+0\n\t"	      :	      :	 "a" (&condition_code), "a" (hwc_data.page)	      :	 "1", "2", "3");#endif	switch (condition_code) {	case HWC_COMMAND_INITIATED:		hwc_data.current_servc = HWC_CMDW_WRITEMASK;		hwc_data.current_hwcb = hwc_data.page;		retval = condition_code;		break;	case HWC_BUSY:		retval = -EBUSY;		break;	default:		retval = -EIO;	}	return retval;}static int write_event_mask_2 (void){	init_hwcb_t *hwcb = (init_hwcb_t *) hwc_data.page;	int retval = 0;	if (hwcb->hwc_receive_mask & ET_Msg_Mask)		hwc_data.write_nonprio = 1;	if (hwcb->hwc_receive_mask & ET_PMsgCmd_Mask)		hwc_data.write_prio = 1;	if (hwcb->hwc_send_mask & ET_OpCmd_Mask)		hwc_data.read_nonprio = 1;	if (hwcb->hwc_send_mask & ET_PMsgCmd_Mask)		hwc_data.read_nonprio = 1;	if ((hwcb->response_code != 0x0020) ||	    (!hwc_data.write_nonprio) ||	    ((!hwc_data.read_nonprio) && (!hwc_data.read_prio)))#ifdef DUMP_HWC_INIT_ERROR		__asm__ ("LHI 1,0xe11\n\t"			 "LRA 2,0(0,%0)\n\t"			 "L 3,0(0,%1)\n\t"			 "J .+0\n\t"	      :	      :	 "a" (hwcb), "a" (&(hwcb->response_code))	      :	 "1", "2", "3");#else		retval = -EIO#endif		    hwc_data.current_servc = 0;	hwc_data.current_hwcb = NULL;	return retval;}static int set_hwc_ioctls (hwc_ioctls_t * ioctls, char correct){	int retval = 0;	hwc_ioctls_t tmp;	if (ioctls->width_htab > MAX_MESSAGE_SIZE) {		if (correct)			tmp.width_htab = MAX_MESSAGE_SIZE;		else			retval = -EINVAL;	} else		tmp.width_htab = ioctls->width_htab;	tmp.echo = ioctls->echo;	if (ioctls->columns > MAX_MESSAGE_SIZE) {		if (correct)			tmp.columns = MAX_MESSAGE_SIZE;		else			retval = -EINVAL;	} else		tmp.columns = ioctls->columns;	switch (ioctls->code) {	case CODE_EBCDIC:	case CODE_ASCII:		tmp.code = ioctls->code;		break;	default:		if (correct)			tmp.code = CODE_ASCII;		else			retval = -EINVAL;	}	tmp.final_nl = ioctls->final_nl;	if (ioctls->max_hwcb < 2) {		if (correct)			tmp.max_hwcb = 2;		else			retval = -EINVAL;	} else		tmp.max_hwcb = ioctls->max_hwcb;	tmp.tolower = ioctls->tolower;	if (ioctls->kmem_hwcb > ioctls->max_hwcb) {		if (correct)			tmp.kmem_hwcb = ioctls->max_hwcb;		else			retval = -EINVAL;	} else		tmp.kmem_hwcb = ioctls->kmem_hwcb;	if (ioctls->kmem_hwcb > MAX_KMEM_PAGES) {		if (correct)			ioctls->kmem_hwcb = MAX_KMEM_PAGES;		else			retval = -EINVAL;	}	if (ioctls->kmem_hwcb < 2) {		if (correct)			ioctls->kmem_hwcb = 2;		else			retval = -EINVAL;	}	tmp.delim = ioctls->delim;	if (!(retval < 0))		hwc_data.ioctls = tmp;	return retval;}int hwc_init (void){	int retval;#ifdef BUFFER_STRESS_TEST	init_hwcb_t *hwcb;	int i;#endif#ifdef CONFIG_3215	if (MACHINE_IS_VM)		return 0;#endif	spin_lock_init (&hwc_data.lock);	retval = write_event_mask_1 ();	if (retval < 0)		return retval;#ifdef USE_VM_DETECTION	if (MACHINE_IS_VM) {		if (hwc_data.init_ioctls.columns > 76)			hwc_data.init_ioctls.columns = 76;		hwc_data.init_ioctls.tolower = 1;		if (!hwc_data.init_ioctls.delim)			hwc_data.init_ioctls.delim = DEFAULT_CASE_DELIMITER;	} else {		hwc_data.init_ioctls.tolower = 0;		hwc_data.init_ioctls.delim = 0;	}#endif	retval = set_hwc_ioctls (&hwc_data.init_ioctls, 1);	hwc_data.kmem_start = (unsigned long)	    alloc_bootmem_pages (hwc_data.ioctls.kmem_hwcb * PAGE_SIZE);	hwc_data.kmem_end = hwc_data.kmem_start +	    hwc_data.ioctls.kmem_hwcb * PAGE_SIZE - 1;	ctl_set_bit (0, 9);#ifdef BUFFER_STRESS_TEST	internal_print (			       DELAYED_WRITE,			       HWC_RW_PRINT_HEADER			       "use %i bytes for buffering.\n",			       hwc_data.ioctls.kmem_hwcb * PAGE_SIZE);	for (i = 0; i < 500; i++) {		hwcb = (init_hwcb_t *) BUF_HWCB;		internal_print (				       DELAYED_WRITE,				       HWC_RW_PRINT_HEADER			  "This is stress test message #%i, free: %i bytes\n",				       i,			     MAX_HWCB_ROOM - (hwcb->length + sizeof (mto_t)));	}#endif	return retval;}void do_hwc_interrupt (void){	spin_lock (&hwc_data.lock);	if (!hwc_data.current_servc) {		unconditional_read_1 ();	} else {		switch (hwc_data.current_servc) {		case HWC_CMDW_WRITEMASK:			write_event_mask_2 ();			break;		case HWC_CMDW_WRITEDATA:			write_event_data_2 ();			break;		case HWC_CMDW_READDATA:			unconditional_read_2 ();			break;		}		write_event_data_1 ();	}	wake_up_hwc_tty ();	spin_unlock (&hwc_data.lock);}int hwc_ioctl (unsigned int cmd, unsigned long arg){	hwc_ioctls_t tmp = hwc_data.ioctls;	int retval = 0;	unsigned long flags;	unsigned int obuf;	spin_lock_irqsave (&hwc_data.lock, flags);	switch (cmd) {	case TIOCHWCSHTAB:		if (get_user (tmp.width_htab, (ioctl_htab_t *) arg))			goto fault;		break;	case TIOCHWCSECHO:		if (get_user (tmp.echo, (ioctl_echo_t *) arg))			goto fault;		break;	case TIOCHWCSCOLS:		if (get_user (tmp.columns, (ioctl_cols_t *) arg))			goto fault;		break;	case TIOCHWCSCODE:		if (get_user (tmp.code, (ioctl_code_t *) arg))			goto fault;		break;	case TIOCHWCSNL:		if (get_user (tmp.final_nl, (ioctl_nl_t *) arg))			goto fault;		break;	case TIOCHWCSOBUF:		if (get_user (obuf, (unsigned int *) arg))			goto fault;		if (obuf & 0xFFF)			tmp.max_hwcb = (((obuf | 0xFFF) + 1) >> 12);		else			tmp.max_hwcb = (obuf >> 12);		break;	case TIOCHWCSCASE:		if (get_user (tmp.tolower, (ioctl_case_t *) arg))			goto fault;		break;	case TIOCHWCSDELIM:		if (get_user (tmp.delim, (ioctl_delim_t *) arg))			goto fault;		break;	case TIOCHWCSINIT:		retval = set_hwc_ioctls (&hwc_data.init_ioctls, 1);		break;	case TIOCHWCGHTAB:		if (put_user (tmp.width_htab, (ioctl_htab_t *) arg))			goto fault;		break;	case TIOCHWCGECHO:		if (put_user (tmp.echo, (ioctl_echo_t *) arg))			goto fault;		break;	case TIOCHWCGCOLS:		if (put_user (tmp.columns, (ioctl_cols_t *) arg))			goto fault;		break;	case TIOCHWCGCODE:		if (put_user (tmp.code, (ioctl_code_t *) arg))			goto fault;		break;	case TIOCHWCGNL:		if (put_user (tmp.final_nl, (ioctl_nl_t *) arg))			goto fault;		break;	case TIOCHWCGOBUF:		if (put_user (tmp.max_hwcb, (ioctl_obuf_t *) arg))			goto fault;		break;	case TIOCHWCGKBUF:		if (put_user (tmp.kmem_hwcb, (ioctl_obuf_t *) arg))			goto fault;		break;	case TIOCHWCGCASE:		if (put_user (tmp.tolower, (ioctl_case_t *) arg))			goto fault;		break;	case TIOCHWCGDELIM:		if (put_user (tmp.delim, (ioctl_delim_t *) arg))			goto fault;		break;#if 0	case TIOCHWCGINIT:		if (put_user (&hwc_data.init_ioctls, (hwc_ioctls_t *) arg))			goto fault;		break;	case TIOCHWCGCURR:		if (put_user (&hwc_data.ioctls, (hwc_ioctls_t *) arg))			goto fault;		break;#endif	default:		goto noioctlcmd;	}	if (_IOC_DIR (cmd) == _IOC_WRITE)		retval = set_hwc_ioctls (&tmp, 0);	goto out;      fault:	retval = -EFAULT;	goto out;      noioctlcmd:	retval = -ENOIOCTLCMD;      out:	spin_unlock_irqrestore (&hwc_data.lock, flags);	return retval;}

⌨️ 快捷键说明

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