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

📄 np.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
	    case NPPANIC:		printf("\nPanic from NP100 unit %d!\n",mp->unit);		mp->flags &= ~AVAILABLE;		mp->flags |= PANIC1;		/* Clear device request word */		mp->shmemp->statblock.sb_drw = 0;		panicmap = uballoc(mp->devp->ui_ubanum,(caddr_t)panaddr,sizeof(panaddr),0);		NPIO(mp,(paddr_t)NPPSADDR,(paddr_t)((int)panicmap & UBADDRMASK),sizeof(panaddr),B_READ);		goto out;		break;	    case NPDUMP:		mp->flags |= (DUMPREQ | BOARDREQ);		/* Clear device request word */		mp->shmemp->statblock.sb_drw = 0;		if(NpState & ICPAVAIL)			wakeup((caddr_t)&NpState);		break;	    case NPLOAD:		mp->flags |= (LOADREQ | BOARDREQ);		/* Clear device request word */		mp->shmemp->statblock.sb_drw = 0;		if(NpState & ICPAVAIL)			wakeup((caddr_t)&NpState);		break;	    default:		printf("Bad Req: %x.\n",mp->shmemp->statblock.sb_drw);		goto out;	} 	/* Process the Host Command Queue for this device */	NpProcQueue(mp);out:	CLEARINT(mp);	/* Clear the interrupt */	if(NpDebug & DEBENTRY)		printf("npintr...\n");	return(1);	/* Interrupt serviced */}/* * This routine, called from the interrupt handler, is used to process the * Host Command Queue for the specified device. */NpProcQueue(mp)struct npmaster *mp;{	register struct CmdQue *cqp;	register struct CQE *ep;	register struct npreq *rp;	register int base;	int s;	if(NpDebug & DEBENTRY)		printf("NpProcQueue\n");	cqp = &mp->shmemp->hostcq;	/* Command Queue pointer */	s = spl5();	if(mp->flags & SCANNING) {		splx(s);            	return;	}	mp->flags |= SCANNING;	splx(s);	cqp->scanflag | = ON;	base = (int)mp->shmemp;		/* Shared memory base address */	while(1) {	       	cqp->scanflag |= ON;		cqp->chngflag &= ~ON;		while(ep = NpRemCQE(cqp,base)) {			rp = ep->cqe_reqid;			if(NpDebug & DEBCQE)				printf("cqe_sts is %x ep = %x\n",ep->cqe_sts,ep);			switch (ep->cqe_sts)  {			    case NPDONE:				rp->flags |= REQDONE;	/* Normal completion */				break;			    case NPIFC:			/* IFC Request */				rp->flags |= IOIFC;				break;			    case NPPERR:		/* Protocol Error */				rp->flags |= (NPPERR | REQDONE);				break;			    case NPMERR:		/* Memory allocation */				rp->flags |= (NPMERR | REQDONE);				break;			    default:			/* Error on Board */				rp->flags |= (IOERR | REQDONE);				break;			}			if(NpDebug & DEBCQE) {				printf("flag is %x reqid = %x\n",rp->flags,ep->cqe_reqid);				printf("wakeup in procqueue\n");			}			if(rp->intr) {				if(NpDebug & DEBINTR)					printf("calling usr intr at %x\n",						rp->intr);				/* Call interrupt routine */				(*rp->intr)(mp,rp);			}			else {			if(NpDebug & DEBINTR)				printf("waking up %x\n",rp);				/* if(rp->flags & NPUIO)					iodone(&rp->buf);				else	wakeup((caddr_t) (rp)); /* Awaken */				wakeup((caddr_t)(rp)); 	/* Awaken */			if(NpDebug & DEBINTR)				printf("AWAKE\n");			}		}		cqp->scanflag &= ~ON;		if(!(cqp->chngflag & ON))			break;	}	mp->flags &= ~SCANNING;	if(NpDebug & DEBENTRY)		printf("NpProcQueue...\n");}/* * NpIFC - processes an IFC (Internal Fuction Call) request  *		NOTE: this function must be called from the user context *			on all virtual pageing systems * */NpIFC(mp,rp)register struct npmaster *mp;register struct npreq *rp;{	register struct CQE	*ep;	if(NpDebug & DEBENTRY)		printf("NpIFC\n");	ep = rp->element;	rp->flags &= ~IOIFC;	switch(ep->cqe_func) {	    case NPUNLOCK:	/* Unlock process, free up mapping registers  */		if(NpDebug & DEBIFC)			printf("NPUNLOCK\n");		if(rp->mapbase)			NpUnMapMem(mp,rp);		break;	    case NPLOCK:	/* Lock process, get mapping registers */		if(NpDebug & DEBIFC)			printf("NPLOCK\n");		NpMapMem(mp,rp,rp->virtmem,rp->bytecnt);		ep->cqe_dma[0] = LOWORD(rp->bufaddr);		ep->cqe_dma[1] = HIWORD(rp->bufaddr);		break;	    case NPREMAP:		if(NpDebug & DEBIFC)			printf("NPREMAP\n");		/* Remap user buffer and update buffer offset */#ifdef USG		np_remapmem(rp,rp->virtmem); 		ep->cqe_dma[0] = LOWORD(rp->bufaddr);		ep->cqe_dma[1] = HIWORD(rp->bufaddr);		break;#endif	    default:		if(NpDebug & DEBIFC)			printf("Bad case %x in IFC\n", ep->cqe_func);		rp->flags |= (REQDONE | IOERR);		break;	}}/* * The following contains various routines for allocating and deallocating * structures used by the NP Driver. Routines are also here for addding * and removing Command Queue Elements from a Command Queue. *//* * Get a free NP Request structure from the list pointed to by head. Returns * a pointer to a npreq or NULL if none left. */struct npreq *NpGetReq(head)struct npreq *head;{	register struct npreq *p;	p = head->free;	head->free = p->free;	if (p->flags & REQALOC)		printf("GetReq: Req %x already allocated\n", p);	p->flags &= WANTREQ;	if (p != head)		p->flags |= REQALOC;	return(p==head ? (struct npreq *)NULL : p);}/* * Return a NP Request structure to the free list pointed to by head. */NpFreeReq(head,nprp)register struct npreq *head, *nprp;{	int s;	if(NpDebug & DEBREQ)		printf("NpFreeReq, head is %x rp is %x\n",head,nprp);	if (nprp == NULL) {		printf("FREEREQ: attempt to free null pointer\n");		return;	}	if (!(nprp->flags & REQALOC)) {		printf("FREEREQ: attempt to free unallocated request %x\n",			nprp);		return;	}	if (nprp->flags & REQUSE)		printf("FREEREQ: freeing unremoved request %x\n", nprp);	s = spl5();	nprp->forw = nprp->back = (struct npreq *)NULL;	nprp->free = head->free;	head->free = nprp;	nprp->flags &= ~REQALOC;	splx(s);	/* Wake up any processes waiting for a request structure */	if(head->flags & WANTREQ) {		head->flags &= ~WANTREQ;		wakeup((caddr_t)head);	}	if(NpDebug & DEBENTRY)		printf("NpFreeReq...\n");}/* * Add a Command Queue Element onto the specified Command Queue and * update its Add offset. */NpAddCQE(ep,cqp,mp)struct CQE *ep;struct CmdQue *cqp;struct npmaster *mp;{	register unsign16 *temp;	register unsign16 cqe_offset;	register int base;	base = (int)mp->shmemp;		/* Shared memory base address */	temp = (unsign16 *)(base + cqp->cq_add); /* Offset to add element */	cqe_offset = (unsign16)((int)ep - base);	if(*temp) {			/* Should never happen */		printf("No more room on Command Queue!\n");		return;	}	else *temp = cqe_offset;	/* Enter this request's offset */	/* Update cqe_add where next request is to be added */	cqp->cq_add += sizeof(unsign16);	if(cqp->cq_add == cqp->cq_wrap)	/* Wrap if necessary */		cqp->cq_add = (unsign16)((int)cqp->cq_cqe - base);	cqp->chngflag |= ON;		/* Set change flag unconditionally */	/* Interrupt the Board if his scan flag isn't on */	if(!(cqp->scanflag & ON))		INTNI(mp);		/* Interrupt the Board */}/* * The NpRemCQE routine is used to remove the next CQE from the Command Queue * specified by cqp. The common offset of shared memory used by the device * is specified by base. NpRemCQE returns a pointer to the next CQE or * NULL if there are none left. This routine will also update the cqe_rem * offset which specifies where the next element to be removed from the * queue is located. */struct CQE *NpRemCQE(cqp,base)struct CmdQue *cqp;int base;{	register unsign16 *temp;	register unsign16 cqe_offset;	cqp->chngflag &= ~ON;			/* Turn off unconditionally */	/* Get address of element to remove */	temp = (unsign16 *)(base +cqp->cq_rem);	if(*temp == NULL)			/* If none left, go home */		return((struct CQE *) NULL);	else cqe_offset = *temp;		/* Offset of CQE to remove */	/* Update the Command Queue's cqe_rem offset */	*temp = NULL;				/* Clear out this entry */	cqp->cq_rem += sizeof(unsign16);	/* Bump offset */	if(cqp->cq_rem == cqp->cq_wrap)		/* Wrap if necessary */		cqp->cq_rem = (unsign16)((int)cqp->cq_cqe - base);	temp = (unsign16 *)(base + cqe_offset);	/* CQE address */	return((struct CQE *)temp);		/* is returned */}/* * NpAddReq will add the specified npreq structure to the queue controlled * by head. */NpAddReq(head,rp)register struct npreq *head, *rp;{	int s;	if (NpDebug & (DEBENTRY|DEBREQ))		printf("NpAddReq: %x\n",rp);	if (rp->flags & REQUSE)		printf("ADDREQ: Request %x allready in use\n", rp);	s = spl7();	rp->forw = head->forw;	rp->forw->back = rp;	rp->back = head;	head->forw = rp;	rp->flags |= REQUSE;	splx(s);	if(NpDebug & DEBENTRY)		printf("NpAddReq...\n");}/* * NpRemReq is used to remove a npreq structure from the queue specified by * head. */NpRemReq(rp)register struct npreq *rp;{	int s;	if (NpDebug & (DEBENTRY|DEBREQ))		printf("NpRemReq: %x\n",rp);	if (rp == NULL) {		printf("REMREQ: null pointer removal requested\n");		return;	}	if (!(rp->flags & REQUSE)) {		printf("REMREQ: trying to rem unused req %x\n", rp);		return;	}	if (!(rp->flags & REQALOC)) {		printf("REMREQ: trying to rem unallocated req %x\n", rp);		return;	}			s = spl7();	rp->back->forw = rp->forw;	rp->forw->back = rp->back;	rp->flags &= ~REQUSE;	splx(s);	if(NpDebug & DEBENTRY)		printf("NpRemReq...\n");}/* * The following routines are used to communicate with the * NI Hardware via the CSR0 commands. These commands are issued during * the hardware initializtion process and may also be used subsequently * by privileged processes who wish to communicate in this way. The * convention for passing data as a Command Block is discussed in detail * in the NI1510 UNIBUS Compatible Ethernet Communications Processor * Hardware Specification. */NpSendCSR0(iobase,src,bcount)struct NPREG *iobase;register unsign16 *src;int bcount;{	register int wcount;	int i;	int csrflag;	unsign16 tmp;	if(NpDebug & DEBENTRY)		printf("NpSendCSR0\n");	/* Jolt the board into CSR0 command mode if necessary */	if(!(RCSR1(iobase) & NPENB)){   		tmp = NPCLEAR;		/* MC68000 clr reads before writing */		WCSR0(iobase,tmp); 		}	wcount = (bcount +1) >> 1;	/* Convert byte count to word count */	/* Clear timer flag before beginning the timer */	csrflag = NPCLEAR;	timeout(NpTimer,&csrflag,DIAGTIME);	for(i = 0; (i < wcount) & (csrflag == NPCLEAR); i++) {		while(! ((RCSR1(iobase) & NPENB) && (RCSR1(iobase) & NPRDY)))			if(csrflag) break;		WCSR0(iobase,*src);		src++;			/* Better do this WCSR is a macro */	}	/* Clear the timer entry */	untimeout(NpTimer,&csrflag);	/* Error if timer went off */	if(csrflag)		return(EIO);		if(NpDebug & DEBENTRY)		printf("NpSendCSR0...\n");	return(0);}/* * NpSetIntLev sets the UNIBUS interrupt vector to be used by the NP board when * interupting the host. The board is specified by mp. */NpSetIntLevel(mp,level)struct npmaster *mp;int level;{	struct {		unsign16 cmd_word;		unsign16 int_level;	}cmd_block;	cmd_block.cmd_word = NPCBI | CBICNT;	cmd_block.int_level = level;	return(NpSendCSR0(mp->iobase,(unsign16 *)&cmd_block,(int)sizeof(cmd_block)));}/* * NpSetMemAddr is used to declare the shared memory area address to be used * for communication between the driver and the device. This address is used * to access data structures by acting as a base from which defined offsets * locate data. The board is specified by mp. */NpSetMemAddr(mp,addr)struct npmaster *mp;caddr_t addr;{	caddr_t shmaddr;	int error;	struct {		unsign16 cmd_word;		unsign16 hi_addr;		unsign16 lo_addr;	} cmd_block;	if(NpDebug & DEBENTRY)		printf("NpSetMemAddr\n");	shmaddr = addr;	if(NpDebug & DEBMEM)		printf("NpSetMemAddr, addr is %x shmaddr is %x.\n",addr,shmaddr);	cmd_block.cmd_word = NPCMD | CMDCNT;	cmd_block.hi_addr = HIWORD(shmaddr);	cmd_block.lo_addr = LOWORD(shmaddr);	error = NpSendCSR0(mp->iobase,(unsign16 *)&cmd_block,(int)sizeof(cmd_block));	if(NpDebug & DEBENTRY)		printf("NpSetMemAddr...\n");	return(error);}/* * NpSetXeqAddr specifies the address at which the board should begin * execution of its on-board software. It also indicates the shared memory

⌨️ 快捷键说明

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