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

📄 isar.c

📁 arm平台上的uclinux系统全部源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: isar.c,v 1.1.1.1 1999/11/15 13:42:19 vadim Exp $ * isar.c   ISAR (Siemens PSB 7110) specific routines * * Author       Karsten Keil (keil@isdn4linux.de) * * * $Log: isar.c,v $ * Revision 1.1.1.1  1999/11/15 13:42:19  vadim * Initial import * * Revision 1.1.2.4  1998/11/03 00:06:44  keil * certification related changes * fixed logging for smaller stack use * * Revision 1.1.2.3  1998/10/04 23:04:58  keil * ISAR works now * * Revision 1.1.2.2  1998/09/30 22:28:07  keil * more work for isar support * * Revision 1.1.2.1  1998/09/27 13:01:43  keil * Start support for ISAR based cards * * Revision 1.1  1998/08/13 23:33:47  keil * First version, only init * * */#define __NO_VERSION__#include "hisax.h"#include "isar.h"#include "isdnl1.h"#include <linux/interrupt.h>#define DBG_LOADFIRM	0#define DUMP_MBOXFRAME	2#define MIN(a,b) ((a<b)?a:b)void isar_setup(struct IsdnCardState *cs);static inline intwaitforHIA(struct IsdnCardState *cs, int timeout){	while ((cs->BC_Read_Reg(cs, 0, ISAR_HIA) & 1) && timeout) {		udelay(1);		timeout--;	}	if (!timeout)		printk(KERN_WARNING "HiSax: ISAR waitforHIA timeout\n");	return(timeout);}intsendmsg(struct IsdnCardState *cs, u_char his, u_char creg, u_char len,	u_char *msg){	long flags;	int i;		if (!waitforHIA(cs, 4000))		return(0);#if DUMP_MBOXFRAME	if (cs->debug & L1_DEB_HSCX)		debugl1(cs, "sendmsg(%02x,%02x,%d)", his, creg, len);#endif	save_flags(flags);	cli();	cs->BC_Write_Reg(cs, 0, ISAR_CTRL_H, creg);	cs->BC_Write_Reg(cs, 0, ISAR_CTRL_L, len);	cs->BC_Write_Reg(cs, 0, ISAR_WADR, 0);	if (msg && len) {		cs->BC_Write_Reg(cs, 1, ISAR_MBOX, msg[0]);		for (i=1; i<len; i++)			cs->BC_Write_Reg(cs, 2, ISAR_MBOX, msg[i]);#if DUMP_MBOXFRAME>1		if (cs->debug & L1_DEB_HSCX_FIFO) {			char tmp[256], *t;						i = len;			while (i>0) {				t = tmp;				t += sprintf(t, "sendmbox cnt %d", len);				QuickHex(t, &msg[len-i], (i>64) ? 64:i);				debugl1(cs, tmp);				i -= 64;			}		}#endif	}	cs->BC_Write_Reg(cs, 1, ISAR_HIS, his);	restore_flags(flags);	waitforHIA(cs, 10000);	return(1);}/* Call only with IRQ disabled !!! */inline voidrcv_mbox(struct IsdnCardState *cs, struct isar_reg *ireg, u_char *msg){	int i;	cs->BC_Write_Reg(cs, 1, ISAR_RADR, 0);	if (msg && ireg->clsb) {		msg[0] = cs->BC_Read_Reg(cs, 1, ISAR_MBOX);		for (i=1; i < ireg->clsb; i++)			 msg[i] = cs->BC_Read_Reg(cs, 2, ISAR_MBOX);#if DUMP_MBOXFRAME>1		if (cs->debug & L1_DEB_HSCX_FIFO) {			char tmp[256], *t;						i = ireg->clsb;			while (i>0) {				t = tmp;				t += sprintf(t, "rcv_mbox cnt %d", ireg->clsb);				QuickHex(t, &msg[ireg->clsb-i], (i>64) ? 64:i);				debugl1(cs, tmp);				i -= 64;			}		}#endif	}	cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);}/* Call only with IRQ disabled !!! */inline voidget_irq_infos(struct IsdnCardState *cs, struct isar_reg *ireg){	ireg->iis = cs->BC_Read_Reg(cs, 1, ISAR_IIS);	ireg->cmsb = cs->BC_Read_Reg(cs, 1, ISAR_CTRL_H);	ireg->clsb = cs->BC_Read_Reg(cs, 1, ISAR_CTRL_L);#if DUMP_MBOXFRAME	if (cs->debug & L1_DEB_HSCX)		debugl1(cs, "rcv_mbox(%02x,%02x,%d)", ireg->iis, ireg->cmsb,			ireg->clsb);#endif}intwaitrecmsg(struct IsdnCardState *cs, u_char *len,	u_char *msg, int maxdelay){	int timeout = 0;	long flags;	struct isar_reg *ir = cs->bcs[0].hw.isar.reg;			while((!(cs->BC_Read_Reg(cs, 0, ISAR_IRQBIT) & ISAR_IRQSTA)) &&		(timeout++ < maxdelay))		udelay(1);	if (timeout >= maxdelay) {		printk(KERN_WARNING"isar recmsg IRQSTA timeout\n");		return(0);	}	save_flags(flags);	cli();	get_irq_infos(cs, ir);	rcv_mbox(cs, ir, msg);	*len = ir->clsb;	restore_flags(flags);	return(1);}intISARVersion(struct IsdnCardState *cs, char *s){	int ver;	u_char msg[] = ISAR_MSG_HWVER;	u_char tmp[64];	u_char len;	int debug;	cs->cardmsg(cs, CARD_RESET,  NULL);	/* disable ISAR IRQ */	cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0);	debug = cs->debug;	cs->debug &= ~(L1_DEB_HSCX | L1_DEB_HSCX_FIFO);	if (!sendmsg(cs, ISAR_HIS_VNR, 0, 3, msg))		return(-1);	if (!waitrecmsg(cs, &len, tmp, 100000))		 return(-2);	cs->debug = debug;	if (cs->bcs[0].hw.isar.reg->iis == ISAR_IIS_VNR) {		if (len == 1) {			ver = tmp[0] & 0xf;			printk(KERN_INFO "%s ISAR version %d\n", s, ver);			return(ver);		}		return(-3);	}	return(-4);}intisar_load_firmware(struct IsdnCardState *cs, u_char *buf){	int ret, size, cnt, debug;	u_char len, nom, noc;	u_short sadr, left, *sp;	u_char *p = buf;	u_char *msg, *tmpmsg, *mp, tmp[64];	long flags;	struct isar_reg *ireg = cs->bcs[0].hw.isar.reg;		struct {u_short sadr;		u_short len;		u_short d_key;	} blk_head;		#define	BLK_HEAD_SIZE 6	if (1 != (ret = ISARVersion(cs, "Testing"))) {		printk(KERN_ERR"isar_load_firmware wrong isar version %d\n", ret);		return(1);	}	debug = cs->debug;#if DBG_LOADFIRM<2	cs->debug &= ~(L1_DEB_HSCX | L1_DEB_HSCX_FIFO);#endif	printk(KERN_DEBUG"isar_load_firmware buf %#lx\n", (u_long)buf);	if ((ret = verify_area(VERIFY_READ, (void *) p, sizeof(int)))) {		printk(KERN_ERR"isar_load_firmware verify_area ret %d\n", ret);		return ret;	}	if ((ret = copy_from_user(&size, p, sizeof(int)))) {		printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", ret);		return ret;	}	p += sizeof(int);	printk(KERN_DEBUG"isar_load_firmware size: %d\n", size);	if ((ret = verify_area(VERIFY_READ, (void *) p, size))) {		printk(KERN_ERR"isar_load_firmware verify_area ret %d\n", ret);		return ret;	}	cnt = 0;	/* disable ISAR IRQ */	cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0);	if (!(msg = kmalloc(256, GFP_KERNEL))) {		printk(KERN_ERR"isar_load_firmware no buffer\n");		return (1);	}	if (!(tmpmsg = kmalloc(256, GFP_KERNEL))) {		printk(KERN_ERR"isar_load_firmware no tmp buffer\n");		kfree(msg);		return (1);	}	while (cnt < size) {		if ((ret = copy_from_user(&blk_head, p, BLK_HEAD_SIZE))) {			printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", ret);			goto reterror;		}		cnt += BLK_HEAD_SIZE;		p += BLK_HEAD_SIZE;		printk(KERN_DEBUG"isar firmware block (%#x,%5d,%#x)\n",			blk_head.sadr, blk_head.len, blk_head.d_key & 0xff);		sadr = blk_head.sadr;		left = blk_head.len;		if (!sendmsg(cs, ISAR_HIS_DKEY, blk_head.d_key & 0xff, 0, NULL)) {			printk(KERN_ERR"isar sendmsg dkey failed\n");			ret = 1;goto reterror;		}		if (!waitrecmsg(cs, &len, tmp, 100000)) {			printk(KERN_ERR"isar waitrecmsg dkey failed\n");			ret = 1;goto reterror;		}		if ((ireg->iis != ISAR_IIS_DKEY) || ireg->cmsb || len) {			printk(KERN_ERR"isar wrong dkey response (%x,%x,%x)\n",				ireg->iis, ireg->cmsb, len);			ret = 1;goto reterror;		}		while (left>0) {			noc = MIN(126, left);			nom = 2*noc;			mp  = msg;			*mp++ = sadr / 256;			*mp++ = sadr % 256;			left -= noc;			*mp++ = noc;			if ((ret = copy_from_user(tmpmsg, p, nom))) {				printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", ret);				goto reterror;			}			p += nom;			cnt += nom;			nom += 3;			sp = (u_short *)tmpmsg;#if DBG_LOADFIRM			printk(KERN_DEBUG"isar: load %3d words at %04x\n",				 noc, sadr);#endif			sadr += noc;			while(noc) {				*mp++ = *sp / 256;				*mp++ = *sp % 256;				sp++;				noc--;			}			if (!sendmsg(cs, ISAR_HIS_FIRM, 0, nom, msg)) {				printk(KERN_ERR"isar sendmsg prog failed\n");				ret = 1;goto reterror;			}			if (!waitrecmsg(cs, &len, tmp, 100000)) {				printk(KERN_ERR"isar waitrecmsg prog failed\n");				ret = 1;goto reterror;			}			if ((ireg->iis != ISAR_IIS_FIRM) || ireg->cmsb || len) {				printk(KERN_ERR"isar wrong prog response (%x,%x,%x)\n",					ireg->iis, ireg->cmsb, len);				ret = 1;goto reterror;			}		}		printk(KERN_DEBUG"isar firmware block %5d words loaded\n",			blk_head.len);	}	msg[0] = 0xff;	msg[1] = 0xfe;	ireg->bstat = 0;	if (!sendmsg(cs, ISAR_HIS_STDSP, 0, 2, msg)) {		printk(KERN_ERR"isar sendmsg start dsp failed\n");		ret = 1;goto reterror;	}	if (!waitrecmsg(cs, &len, tmp, 100000)) {		printk(KERN_ERR"isar waitrecmsg start dsp failed\n");		ret = 1;goto reterror;	}	if ((ireg->iis != ISAR_IIS_STDSP) || ireg->cmsb || len) {		printk(KERN_ERR"isar wrong start dsp response (%x,%x,%x)\n",			ireg->iis, ireg->cmsb, len);		ret = 1;goto reterror;	} else		printk(KERN_DEBUG"isar start dsp success\n");	/* NORMAL mode entered */	/* Enable IRQs of ISAR */	cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, ISAR_IRQSTA);	save_flags(flags);	sti();	cnt = 1000; /* max 1s */	while ((!ireg->bstat) && cnt) {		udelay(1000);		cnt--;	}	if (!cnt) {		printk(KERN_ERR"isar no general status event received\n");		ret = 1;goto reterrflg;	} else {		printk(KERN_DEBUG"isar general status event %x\n",			ireg->bstat);	}	ireg->iis = 0;	if (!sendmsg(cs, ISAR_HIS_DIAG, ISAR_CTRL_STST, 0, NULL)) {		printk(KERN_ERR"isar sendmsg self tst failed\n");		ret = 1;goto reterrflg;	}	cnt = 1000; /* max 10 ms */	while ((ireg->iis != ISAR_IIS_DIAG) && cnt) {		udelay(10);		cnt--;	}	if (!cnt) {		printk(KERN_ERR"isar no self tst response\n");		ret = 1;goto reterrflg;	} else if ((ireg->cmsb == ISAR_CTRL_STST) && (ireg->clsb == 1)		&& (ireg->par[0] == 0)) {		printk(KERN_DEBUG"isar selftest OK\n");	} else {		printk(KERN_DEBUG"isar selftest not OK %x/%x/%x\n",			ireg->cmsb, ireg->clsb, ireg->par[0]);		ret = 1;goto reterror;	}	ireg->iis = 0;	if (!sendmsg(cs, ISAR_HIS_DIAG, ISAR_CTRL_SWVER, 0, NULL)) {		printk(KERN_ERR"isar RQST SVN failed\n");		ret = 1;goto reterror;	}	cnt = 10000; /* max 100 ms */	while ((ireg->iis != ISAR_IIS_DIAG) && cnt) {		udelay(10);		cnt--;	}	if (!cnt) {		printk(KERN_ERR"isar no SVN response\n");		ret = 1;goto reterrflg;	} else {		if ((ireg->cmsb == ISAR_CTRL_SWVER) && (ireg->clsb == 1))			printk(KERN_DEBUG"isar software version %#x\n",				ireg->par[0]);		else {			printk(KERN_ERR"isar wrong swver response (%x,%x) cnt(%d)\n",				ireg->cmsb, ireg->clsb, cnt);			ret = 1;goto reterrflg;		}	}	cs->debug = debug;	isar_setup(cs);	ret = 0;reterrflg:	restore_flags(flags);reterror:	cs->debug = debug;	if (ret)		/* disable ISAR IRQ */		cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0);	kfree(msg);	kfree(tmpmsg);	return(ret);}voidisar_sched_event(struct BCState *bcs, int event){	bcs->event |= 1 << event;	queue_task(&bcs->tqueue, &tq_immediate);	mark_bh(IMMEDIATE_BH);}static inline voidisar_rcv_frame(struct IsdnCardState *cs, struct BCState *bcs){	u_char *ptr;	struct sk_buff *skb;	struct isar_reg *ireg = bcs->hw.isar.reg;		if (!ireg->clsb) {		debugl1(cs, "isar zero len frame");		cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);		return;	}	switch (bcs->mode) {	case L1_MODE_NULL:		debugl1(cs, "isar mode 0 spurious IIS_RDATA %x/%x/%x",			ireg->iis, ireg->cmsb, ireg->clsb);		printk(KERN_WARNING"isar mode 0 spurious IIS_RDATA %x/%x/%x\n",			ireg->iis, ireg->cmsb, ireg->clsb);		cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);		break;	case L1_MODE_TRANS:		if ((skb = dev_alloc_skb(ireg->clsb))) {			SET_SKB_FREE(skb);			rcv_mbox(cs, ireg, (u_char *)skb_put(skb, ireg->clsb));			skb_queue_tail(&bcs->rqueue, skb);			isar_sched_event(bcs, B_RCVBUFREADY);		} else {			printk(KERN_WARNING "HiSax: skb out of memory\n");			cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);		}		break;	case L1_MODE_HDLC:		if ((bcs->hw.isar.rcvidx + ireg->clsb) > HSCX_BUFMAX) {			if (cs->debug & L1_DEB_WARN)				debugl1(cs, "isar_rcv_frame: incoming packet too large");			cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);			bcs->hw.isar.rcvidx = 0;		} else if (ireg->cmsb & HDLC_ERROR) {			if (cs->debug & L1_DEB_WARN)				debugl1(cs, "isar frame error %x len %d",					ireg->cmsb, ireg->clsb);			bcs->hw.isar.rcvidx = 0;			cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);		} else {			if (ireg->cmsb & HDLC_FSD)				bcs->hw.isar.rcvidx = 0;			ptr = bcs->hw.isar.rcvbuf + bcs->hw.isar.rcvidx;			bcs->hw.isar.rcvidx += ireg->clsb;			rcv_mbox(cs, ireg, ptr);			if (ireg->cmsb & HDLC_FED) {				if (bcs->hw.isar.rcvidx < 3) { /* last 2 bytes are the FCS */					printk(KERN_WARNING "ISAR: HDLC frame too short(%d)\n",						bcs->hw.isar.rcvidx);				} else if (!(skb = dev_alloc_skb(bcs->hw.isar.rcvidx-2)))					printk(KERN_WARNING "ISAR: receive out of memory\n");				else {					SET_SKB_FREE(skb);					memcpy(skb_put(skb, bcs->hw.isar.rcvidx-2),

⌨️ 快捷键说明

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