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

📄 hil_mlc.c

📁 QQ2440板子
💻 C
📖 第 1 页 / 共 2 页
字号:
	/* Only enter here if response just received */	/* 27 HILSEN_DISC */	OUT_DISC(HIL_PKT_CMD | HIL_CMD_IDD)	EXPECT_DISC(HIL_PKT_CMD | HIL_CMD_IDD | HIL_ERR_INT,	       20000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_START)	FUNC(hilse_inc_ddi,  0,	HILSEN_NEXT,	HILSEN_START,	0)	FUNC(hilse_take_idd, 0,	HILSEN_MATCH,	HILSEN_IFCACF,	HILSEN_FOLLOW)	OUT_LAST(HIL_PKT_CMD | HIL_CMD_RSC)	EXPECT_LAST(HIL_PKT_CMD | HIL_CMD_RSC | HIL_ERR_INT,	       30000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_DSR)	FUNC(hilse_take_rsc, 0,	HILSEN_MATCH,	0,		HILSEN_FOLLOW)	OUT_LAST(HIL_PKT_CMD | HIL_CMD_EXD)	EXPECT_LAST(HIL_PKT_CMD | HIL_CMD_EXD | HIL_ERR_INT,	       30000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_DSR)	FUNC(hilse_take_exd, 0,	HILSEN_MATCH,	0,		HILSEN_FOLLOW)	OUT_LAST(HIL_PKT_CMD | HIL_CMD_RNM)	EXPECT_LAST(HIL_PKT_CMD | HIL_CMD_RNM | HIL_ERR_INT,	       30000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_DSR)	FUNC(hilse_take_rnm, 0, HILSEN_MATCH,	0,		0)	/* 40 HILSEN_MATCH */	FUNC(hilse_match, 0,	HILSEN_NEXT,	HILSEN_NEXT,	/* TODO */ 0)	/* 41 HILSEN_OPERATE */	OUT(HIL_PKT_CMD | HIL_CMD_POL)	EXPECT(HIL_PKT_CMD | HIL_CMD_POL | HIL_ERR_INT,	       20000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_NEXT)	FUNC(hilse_operate, 0,	HILSEN_OPERATE,	HILSEN_IFC,	HILSEN_NEXT)	/* 44 HILSEN_PROBE */	OUT_LAST(HIL_PKT_CMD | HIL_CMD_EPT)	IN(10000, 		HILSEN_DISC,	HILSEN_DSR,	HILSEN_NEXT)	OUT_DISC(HIL_PKT_CMD | HIL_CMD_ELB)	IN(10000,		HILSEN_DISC,	HILSEN_DSR,	HILSEN_NEXT)	OUT(HIL_PKT_CMD | HIL_CMD_ACF | 1)	IN(10000,		HILSEN_DISC0,	HILSEN_DSR,	HILSEN_NEXT)	OUT_LAST(HIL_PKT_CMD | HIL_CMD_ELB)	IN(10000,		HILSEN_OPERATE,	HILSEN_DSR,	HILSEN_DSR)	/* 52 HILSEN_DSR */	FUNC(hilse_set_ddi, -1,	HILSEN_NEXT,	0,		0)	OUT(HIL_PKT_CMD | HIL_CMD_DSR)	IN(20000, 		HILSEN_DHR,	HILSEN_DHR,	HILSEN_IFC)	/* 55 HILSEN_REPOLL */	OUT(HIL_PKT_CMD | HIL_CMD_RPL)	EXPECT(HIL_PKT_CMD | HIL_CMD_RPL | HIL_ERR_INT,	       20000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_NEXT)	FUNC(hilse_operate, 1,	HILSEN_OPERATE,	HILSEN_IFC,	HILSEN_PROBE)	/* 58 HILSEN_IFCACF */  	OUT(HIL_PKT_CMD | HIL_CMD_IFC)	EXPECT(HIL_PKT_CMD | HIL_CMD_IFC | HIL_ERR_INT,	       20000,		HILSEN_ACF2,	HILSEN_DHR2,	HILSEN_HEAL)	/* 60 HILSEN_END */};static inline void hilse_setup_input(hil_mlc *mlc, struct hilse_node *node) {	switch (node->act) {	case HILSE_EXPECT_DISC:		mlc->imatch = node->object.packet;		mlc->imatch |= ((mlc->ddi + 2) << HIL_PKT_ADDR_SHIFT);		break;	case HILSE_EXPECT_LAST:		mlc->imatch = node->object.packet;		mlc->imatch |= ((mlc->ddi + 1) << HIL_PKT_ADDR_SHIFT);		break;	case HILSE_EXPECT:		mlc->imatch = node->object.packet;		break;	case HILSE_IN:		mlc->imatch = 0;		break;	default:		BUG();	}	mlc->istarted = 1;	mlc->intimeout = node->arg;	do_gettimeofday(&(mlc->instart));	mlc->icount = 15;	memset(mlc->ipacket, 0, 16 * sizeof(hil_packet));	if (down_trylock(&(mlc->isem))) BUG();	return;}#ifdef HIL_MLC_DEBUGstatic int doze = 0;static int seidx; /* For debug */static int kick = 1;#endifstatic int hilse_donode (hil_mlc *mlc) {	struct hilse_node *node;	int nextidx = 0;	int sched_long = 0;	unsigned long flags;#ifdef HIL_MLC_DEBUG	if (mlc->seidx && (mlc->seidx != seidx)  && mlc->seidx != 41 && mlc->seidx != 42 && mlc->seidx != 43) {	  printk(KERN_DEBUG PREFIX "z%i \n%s {%i}", doze, kick ? "K" : "", mlc->seidx);		doze = 0;	}	kick = 0;	seidx = mlc->seidx;#endif	node = hil_mlc_se + mlc->seidx;	switch (node->act) {		int rc;		hil_packet pack;	case HILSE_FUNC:		if (node->object.func == NULL) break;		rc = node->object.func(mlc, node->arg);		nextidx = (rc > 0) ? node->ugly : 			((rc < 0) ? node->bad : node->good);		if (nextidx == HILSEN_FOLLOW) nextidx = rc;		break;	case HILSE_EXPECT_LAST:	case HILSE_EXPECT_DISC:	case HILSE_EXPECT:	case HILSE_IN:		/* Already set up from previous HILSE_OUT_* */		write_lock_irqsave(&(mlc->lock), flags);		rc = mlc->in(mlc, node->arg);		if (rc == 2)  {			nextidx = HILSEN_DOZE;			sched_long = 1;			write_unlock_irqrestore(&(mlc->lock), flags);			break;		}		if (rc == 1)		nextidx = node->ugly;		else if (rc == 0)	nextidx = node->good;		else			nextidx = node->bad;		mlc->istarted = 0;		write_unlock_irqrestore(&(mlc->lock), flags);		break;	case HILSE_OUT_LAST:		write_lock_irqsave(&(mlc->lock), flags);		pack = node->object.packet;		pack |= ((mlc->ddi + 1) << HIL_PKT_ADDR_SHIFT);		goto out;	case HILSE_OUT_DISC:		write_lock_irqsave(&(mlc->lock), flags);		pack = node->object.packet;		pack |= ((mlc->ddi + 2) << HIL_PKT_ADDR_SHIFT);		goto out;	case HILSE_OUT:		write_lock_irqsave(&(mlc->lock), flags);		pack = node->object.packet;	out:		if (mlc->istarted) goto out2;		/* Prepare to receive input */		if ((node + 1)->act & HILSE_IN)			hilse_setup_input(mlc, node + 1);	out2:		write_unlock_irqrestore(&(mlc->lock), flags);		if (down_trylock(&mlc->osem)) {			nextidx = HILSEN_DOZE;			break;		}		up(&mlc->osem);		write_lock_irqsave(&(mlc->lock), flags);		if (!(mlc->ostarted)) {			mlc->ostarted = 1;			mlc->opacket = pack;			mlc->out(mlc);			nextidx = HILSEN_DOZE;			write_unlock_irqrestore(&(mlc->lock), flags);			break;		}		mlc->ostarted = 0;		do_gettimeofday(&(mlc->instart));		write_unlock_irqrestore(&(mlc->lock), flags);		nextidx = HILSEN_NEXT;		break;	case HILSE_CTS:		nextidx = mlc->cts(mlc) ? node->bad : node->good;		break;	default:		BUG();		nextidx = 0;		break;	}#ifdef HIL_MLC_DEBUG	if (nextidx == HILSEN_DOZE) doze++;#endif	while (nextidx & HILSEN_SCHED) {		struct timeval tv;		if (!sched_long) goto sched;		do_gettimeofday(&tv);		tv.tv_usec += 1000000 * (tv.tv_sec - mlc->instart.tv_sec);		tv.tv_usec -= mlc->instart.tv_usec;		if (tv.tv_usec >= mlc->intimeout) goto sched;		tv.tv_usec = (mlc->intimeout - tv.tv_usec) * HZ / 1000000;		if (!tv.tv_usec) goto sched;		mod_timer(&hil_mlcs_kicker, jiffies + tv.tv_usec);		break;	sched:		tasklet_schedule(&hil_mlcs_tasklet);		break;	} 	if (nextidx & HILSEN_DOWN) mlc->seidx += nextidx & HILSEN_MASK;	else if (nextidx & HILSEN_UP) mlc->seidx -= nextidx & HILSEN_MASK;	else mlc->seidx = nextidx & HILSEN_MASK;	if (nextidx & HILSEN_BREAK)	return 1;	return 0;}/******************** tasklet context functions **************************/static void hil_mlcs_process(unsigned long unused) {	struct list_head *tmp;	read_lock(&hil_mlcs_lock);	list_for_each(tmp, &hil_mlcs) {		struct hil_mlc *mlc = list_entry(tmp, hil_mlc, list);		while (hilse_donode(mlc) == 0) {#ifdef HIL_MLC_DEBUG		  if (mlc->seidx != 41 && 		      mlc->seidx != 42 && 		      mlc->seidx != 43) 		    printk(KERN_DEBUG PREFIX " + ");#endif		};	}	read_unlock(&hil_mlcs_lock);}/************************* Keepalive timer task *********************/void hil_mlcs_timer (unsigned long data) {	hil_mlcs_probe = 1;	tasklet_schedule(&hil_mlcs_tasklet);	/* Re-insert the periodic task. */	if (!timer_pending(&hil_mlcs_kicker))		mod_timer(&hil_mlcs_kicker, jiffies + HZ);}/******************** user/kernel context functions **********************/static int hil_mlc_serio_write(struct serio *serio, unsigned char c) {	struct hil_mlc_serio_map *map;	struct hil_mlc *mlc;	struct serio_driver *drv;	uint8_t *idx, *last;	map = serio->port_data;	if (map == NULL) {		BUG();		return -EIO;	}	mlc = map->mlc;	if (mlc == NULL) {		BUG();		return -EIO;	}	mlc->serio_opacket[map->didx] |= 		((hil_packet)c) << (8 * (3 - mlc->serio_oidx[map->didx]));	if (mlc->serio_oidx[map->didx] >= 3) {		/* for now only commands */		if (!(mlc->serio_opacket[map->didx] & HIL_PKT_CMD)) 			return -EIO;		switch (mlc->serio_opacket[map->didx] & HIL_PKT_DATA_MASK) {		case HIL_CMD_IDD:			idx = mlc->di[map->didx].idd;			goto emu;		case HIL_CMD_RSC:			idx = mlc->di[map->didx].rsc;			goto emu;		case HIL_CMD_EXD:			idx = mlc->di[map->didx].exd;			goto emu;		case HIL_CMD_RNM:			idx = mlc->di[map->didx].rnm;			goto emu;		default:			break;		}		mlc->serio_oidx[map->didx] = 0;		mlc->serio_opacket[map->didx] = 0;	}	mlc->serio_oidx[map->didx]++;	return -EIO; emu:	drv = serio->drv;	if (drv == NULL) {		BUG();		return -EIO;	}	last = idx + 15;	while ((last != idx) && (*last == 0)) last--;	while (idx != last) {		drv->interrupt(serio, 0, 0, NULL);		drv->interrupt(serio, HIL_ERR_INT >> 16, 0, NULL);		drv->interrupt(serio, 0, 0, NULL);		drv->interrupt(serio, *idx, 0, NULL);		idx++;	}	drv->interrupt(serio, 0, 0, NULL);	drv->interrupt(serio, HIL_ERR_INT >> 16, 0, NULL);	drv->interrupt(serio, HIL_PKT_CMD >> 8, 0, NULL);	drv->interrupt(serio, *idx, 0, NULL);		mlc->serio_oidx[map->didx] = 0;	mlc->serio_opacket[map->didx] = 0;	return 0;}static int hil_mlc_serio_open(struct serio *serio) {	struct hil_mlc_serio_map *map;	struct hil_mlc *mlc;	if (serio->private != NULL) return -EBUSY;	map = serio->port_data;	if (map == NULL) {		BUG();		return -ENODEV;	}	mlc = map->mlc;	if (mlc == NULL) {		BUG();		return -ENODEV;	}	return 0;}static void hil_mlc_serio_close(struct serio *serio) {	struct hil_mlc_serio_map *map;	struct hil_mlc *mlc;	map = serio->port_data;	if (map == NULL) {		BUG();		return;	}	mlc = map->mlc;	if (mlc == NULL) {		BUG();		return;	}	serio->private = NULL;	serio->drv = NULL;	/* TODO wake up interruptable */}int hil_mlc_register(hil_mlc *mlc) {	int i;        unsigned long flags;	if (mlc == NULL) {		return -EINVAL;	}	mlc->istarted = 0;        mlc->ostarted = 0;        rwlock_init(&mlc->lock);        init_MUTEX(&(mlc->osem));        init_MUTEX(&(mlc->isem));        mlc->icount = -1;        mlc->imatch = 0;	mlc->opercnt = 0;        init_MUTEX_LOCKED(&(mlc->csem));	hil_mlc_clear_di_scratch(mlc);	hil_mlc_clear_di_map(mlc, 0);	for (i = 0; i < HIL_MLC_DEVMEM; i++) {		struct serio *mlc_serio;		hil_mlc_copy_di_scratch(mlc, i);		mlc_serio = kmalloc(sizeof(*mlc_serio), GFP_KERNEL);		mlc->serio[i] = mlc_serio;		memset(mlc_serio, 0, sizeof(*mlc_serio));		mlc_serio->type			= SERIO_HIL | SERIO_HIL_MLC;		mlc_serio->write		= hil_mlc_serio_write;		mlc_serio->open			= hil_mlc_serio_open;		mlc_serio->close		= hil_mlc_serio_close;		mlc_serio->port_data		= &(mlc->serio_map[i]);		mlc->serio_map[i].mlc		= mlc;		mlc->serio_map[i].didx		= i;		mlc->serio_map[i].di_revmap	= -1;		mlc->serio_opacket[i]		= 0;		mlc->serio_oidx[i]		= 0;		serio_register_port(mlc_serio);	}	mlc->tasklet = &hil_mlcs_tasklet;	write_lock_irqsave(&hil_mlcs_lock, flags);	list_add_tail(&mlc->list, &hil_mlcs);	mlc->seidx = HILSEN_START;	write_unlock_irqrestore(&hil_mlcs_lock, flags);	tasklet_schedule(&hil_mlcs_tasklet);	return 0;}int hil_mlc_unregister(hil_mlc *mlc) {	struct list_head *tmp;        unsigned long flags;	int i;	if (mlc == NULL)		return -EINVAL;	write_lock_irqsave(&hil_mlcs_lock, flags);	list_for_each(tmp, &hil_mlcs) {		if (list_entry(tmp, hil_mlc, list) == mlc)			goto found;	}	/* not found in list */	write_unlock_irqrestore(&hil_mlcs_lock, flags);	tasklet_schedule(&hil_mlcs_tasklet);	return -ENODEV; found:	list_del(tmp);        write_unlock_irqrestore(&hil_mlcs_lock, flags);	for (i = 0; i < HIL_MLC_DEVMEM; i++) {		serio_unregister_port(mlc->serio[i]);		mlc->serio[i] = NULL;	}	tasklet_schedule(&hil_mlcs_tasklet);	return 0;}/**************************** Module interface *************************/static int __init hil_mlc_init(void){	init_timer(&hil_mlcs_kicker);	hil_mlcs_kicker.expires = jiffies + HZ;	hil_mlcs_kicker.function = &hil_mlcs_timer;	add_timer(&hil_mlcs_kicker);	tasklet_enable(&hil_mlcs_tasklet);	return 0;}                static void __exit hil_mlc_exit(void){	del_timer(&hil_mlcs_kicker);	tasklet_disable(&hil_mlcs_tasklet);	tasklet_kill(&hil_mlcs_tasklet);}                        module_init(hil_mlc_init);module_exit(hil_mlc_exit);

⌨️ 快捷键说明

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