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

📄 hwc_rw.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 4 页
字号:
		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;	condition_code = service_call (HWC_CMDW_WRITEMASK, hwc_data.page);#ifdef DUMP_HWC_INIT_ERROR	if (condition_code == HWC_NOT_OPERATIONAL)		__asm__ ("LHI 1,0xe10\n\t"			 "L 2,0(%0)\n\t"			 "LRA 3,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 (u32 ext_int_param){	init_hwcb_t *hwcb = (init_hwcb_t *) hwc_data.page;	int retval = 0;	if (hwcb->response_code != 0x0020) {#ifdef DUMP_HWC_INIT_ERROR		__asm__ ("LHI 1,0xe11\n\t"			 "LRA 2,0(%0)\n\t"			 "L 3,0(%1)\n\t"			 "J .+0\n\t"	      :	      :	 "a" (hwcb), "a" (&(hwcb->response_code))	      :	 "1", "2", "3");#else		retval = -1;#endif	} else {		if (hwcb->mask_length != 4) {#ifdef DUMP_HWC_INIT_ERROR			__asm__ ("LHI 1,0xe52\n\t"				 "LRA 2,0(%0)\n\t"				 "J .+0 \n\t"		      :		      :	 "a" (hwcb)		      :	 "1", "2");#endif		} else {			retval += eval_hwc_receive_mask			    (hwcb->hwc_receive_mask);			retval += eval_hwc_send_mask (hwcb->hwc_send_mask);		}	}	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;	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 do_hwc_init (void){	int retval;	memcpy (hwc_data.page, &init_hwcb_template, sizeof (init_hwcb_t));	do {		retval = write_event_mask_1 ();		if (retval == -EBUSY) {			hwc_data.flags |= HWC_INIT;			__ctl_store (cr0, 0, 0);			cr0_save = cr0;			cr0 |= 0x00000200;			cr0 &= 0xFFFFF3AC;			__ctl_load (cr0, 0, 0);			asm volatile ("STOSM %0,0x01"				      :"=m" (psw_mask)::"memory");			while (!(hwc_data.flags & HWC_INTERRUPT))				barrier ();			asm volatile ("STNSM %0,0xFE"				      :"=m" (psw_mask)::"memory");			__ctl_load (cr0_save, 0, 0);			hwc_data.flags &= ~HWC_INIT;		}	} while (retval == -EBUSY);	if (retval == -EIO) {		hwc_data.flags |= HWC_BROKEN;		printk (HWC_RW_PRINT_HEADER "HWC not operational\n");	}	return retval;}void hwc_interrupt_handler (struct pt_regs *regs, __u16 code);int hwc_init (void){	int retval;#ifdef BUFFER_STRESS_TEST	init_hwcb_t *hwcb;	int i;#endif	if (register_external_interrupt (0x2401, hwc_interrupt_handler) != 0)		panic ("Couldn't request external interrupts 0x2401");	spin_lock_init (&hwc_data.lock);#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_low_pages (hwc_data.ioctls.kmem_hwcb * PAGE_SIZE);	hwc_data.kmem_end = hwc_data.kmem_start +	    hwc_data.ioctls.kmem_hwcb * PAGE_SIZE - 1;	retval = do_hwc_init ();	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 */ 0;}signed int hwc_register_calls (hwc_high_level_calls_t * calls){	if (calls == NULL)		return -EINVAL;	if (hwc_data.calls != NULL)		return -EBUSY;	hwc_data.calls = calls;	return 0;}signed int hwc_unregister_calls (hwc_high_level_calls_t * calls){	if (hwc_data.calls == NULL)		return -EINVAL;	if (calls != hwc_data.calls)		return -EINVAL;	hwc_data.calls = NULL;	return 0;}int hwc_send (hwc_request_t * req){	unsigned long flags;	int retval;	int cc;	spin_lock_irqsave (&hwc_data.lock, flags);	if (!req || !req->callback || !req->block) {		retval = -EINVAL;		goto unlock;	}	if (hwc_data.request) {		retval = -ENOTSUPP;		goto unlock;	}	cc = service_call (req->word, req->block);	switch (cc) {	case 0:		hwc_data.request = req;		hwc_data.current_servc = req->word;		hwc_data.current_hwcb = req->block;		retval = 0;		break;	case 2:		retval = -EBUSY;		break;	default:		retval = -ENOSYS;	}      unlock:	spin_unlock_irqrestore (&hwc_data.lock, flags);	return retval;}EXPORT_SYMBOL (hwc_send);void do_hwc_callback (u32 ext_int_param){	if (!hwc_data.request || !hwc_data.request->callback)		return;	if ((ext_int_param & HWC_EXT_INT_PARAM_ADDR)	    != (unsigned long) hwc_data.request->block)		return;	hwc_data.request->callback (hwc_data.request);	hwc_data.request = NULL;	hwc_data.current_hwcb = NULL;	hwc_data.current_servc = 0;}void hwc_do_interrupt (u32 ext_int_param){	u32 finished_hwcb = ext_int_param & HWC_EXT_INT_PARAM_ADDR;	u32 evbuf_pending = ext_int_param & HWC_EXT_INT_PARAM_PEND;	if (hwc_data.flags & HWC_PTIMER_RUNS) {		del_timer (&hwc_data.poll_timer);		hwc_data.flags &= ~HWC_PTIMER_RUNS;	}	if (finished_hwcb) {		if ((unsigned long) hwc_data.current_hwcb != finished_hwcb) {			internal_print (					       DELAYED_WRITE,					       HWC_RW_PRINT_HEADER					       "interrupt: mismatch: "					       "ext. int param. (0x%x) vs. "					       "current HWCB (0x%x)\n",					       ext_int_param,					       hwc_data.current_hwcb);		} else {			if (hwc_data.request) {				do_hwc_callback (ext_int_param);			} else {				switch (hwc_data.current_servc) {				case HWC_CMDW_WRITEMASK:					write_event_mask_2 (ext_int_param);					break;				case HWC_CMDW_WRITEDATA:					write_event_data_2 (ext_int_param);					break;				case HWC_CMDW_READDATA:					unconditional_read_2 (ext_int_param);					break;				default:				}			}		}	} else {		if (hwc_data.current_hwcb) {			internal_print (					       DELAYED_WRITE,					       HWC_RW_PRINT_HEADER					       "interrupt: mismatch: "					       "ext. int. param. (0x%x) vs. "					       "current HWCB (0x%x)\n",					       ext_int_param,					       hwc_data.current_hwcb);		}	}	if (evbuf_pending) {		unconditional_read_1 ();	} else {		write_event_data_1 ();	}	if (!hwc_data.calls || !hwc_data.calls->wake_up)		return;	(hwc_data.calls->wake_up) ();}void hwc_interrupt_handler (struct pt_regs *regs, __u16 code){	int cpu = smp_processor_id ();	u32 ext_int_param = hwc_ext_int_param ();	irq_enter (cpu, 0x2401);	if (hwc_data.flags & HWC_INIT) {		hwc_data.flags |= HWC_INTERRUPT;	} else if (hwc_data.flags & HWC_BROKEN) {		if (!do_hwc_init ()) {			hwc_data.flags &= ~HWC_BROKEN;			internal_print (DELAYED_WRITE,					HWC_RW_PRINT_HEADER					"delayed HWC setup after"					" temporary breakdown"					" (ext. int. parameter=0x%x)\n",					ext_int_param);		}	} else {		spin_lock (&hwc_data.lock);		hwc_do_interrupt (ext_int_param);		spin_unlock (&hwc_data.lock);	}	irq_exit (cpu, 0x2401);}void hwc_unblank (void){	spin_lock (&hwc_data.lock);	spin_unlock (&hwc_data.lock);	__ctl_store (cr0, 0, 0);	cr0_save = cr0;	cr0 |= 0x00000200;	cr0 &= 0xFFFFF3AC;	__ctl_load (cr0, 0, 0);	asm volatile ("STOSM %0,0x01":"=m" (psw_mask)::"memory");	while (ALL_HWCB_CHAR)		barrier ();	asm volatile ("STNSM %0,0xFE":"=m" (psw_mask)::"memory");	__ctl_load (cr0_save, 0, 0);}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 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 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 + -