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

📄 boardergo.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: boardergo.c,v 1.5.6.7 2001/11/06 21:58:19 kai Exp $ * * Linux driver for HYSDN cards, specific routines for ergo type boards. * * Author    Werner Cornelius (werner@titro.de) for Hypercope GmbH * Copyright 1999 by Werner Cornelius (werner@titro.de) * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. * * As all Linux supported cards Champ2, Ergo and Metro2/4 use the same * DPRAM interface and layout with only minor differences all related * stuff is done here, not in separate modules. * */#include <linux/config.h>#include <linux/sched.h>#include <linux/signal.h>#include <linux/kernel.h>#include <linux/ioport.h>#include <linux/interrupt.h>#include <linux/vmalloc.h>#include <asm/io.h>#include "hysdn_defs.h"#include "boardergo.h"#define byteout(addr,val) outb(val,addr)#define bytein(addr) inb(addr)/***************************************************//* The cards interrupt handler. Called from system *//***************************************************/static irqreturn_tergo_interrupt(int intno, void *dev_id, struct pt_regs *regs){	hysdn_card *card = dev_id;	/* parameter from irq */	tErgDpram *dpr;	ulong flags;	uchar volatile b;	if (!card)		return IRQ_NONE;		/* error -> spurious interrupt */	if (!card->irq_enabled)		return IRQ_NONE;		/* other device interrupting or irq switched off */	save_flags(flags);	cli();			/* no further irqs allowed */	if (!(bytein(card->iobase + PCI9050_INTR_REG) & PCI9050_INTR_REG_STAT1)) {		restore_flags(flags);	/* restore old state */		return IRQ_NONE;		/* no interrupt requested by E1 */	}	/* clear any pending ints on the board */	dpr = card->dpram;	b = dpr->ToPcInt;	/* clear for ergo */	b |= dpr->ToPcIntMetro;	/* same for metro */	b |= dpr->ToHyInt;	/* and for champ */	/* start kernel task immediately after leaving all interrupts */	if (!card->hw_lock)		schedule_work(&card->irq_queue);	restore_flags(flags);	return IRQ_HANDLED;}				/* ergo_interrupt *//******************************************************************************//* ergo_irq_bh is the function called by the immediate kernel task list after *//* being activated with queue_task and no interrupts active. This task is the *//* only one handling data transfer from or to the card after booting. The task *//* may be queued from everywhere (interrupts included).                       *//******************************************************************************/static voidergo_irq_bh(hysdn_card * card){	tErgDpram *dpr;	int again;	ulong flags;	if (card->state != CARD_STATE_RUN)		return;		/* invalid call */	dpr = card->dpram;	/* point to DPRAM */	save_flags(flags);	cli();	if (card->hw_lock) {		restore_flags(flags);	/* hardware currently unavailable */		return;	}	card->hw_lock = 1;	/* we now lock the hardware */	do {		sti();		/* reenable other ints */		again = 0;	/* assume loop not to be repeated */		if (!dpr->ToHyFlag) {			/* we are able to send a buffer */			if (hysdn_sched_tx(card, dpr->ToHyBuf, &dpr->ToHySize, &dpr->ToHyChannel,					   ERG_TO_HY_BUF_SIZE)) {				dpr->ToHyFlag = 1;	/* enable tx */				again = 1;	/* restart loop */			}		}		/* we are able to send a buffer */		if (dpr->ToPcFlag) {			/* a message has arrived for us, handle it */			if (hysdn_sched_rx(card, dpr->ToPcBuf, dpr->ToPcSize, dpr->ToPcChannel)) {				dpr->ToPcFlag = 0;	/* we worked the data */				again = 1;	/* restart loop */			}		}		/* a message has arrived for us */		cli();		/* no further ints */		if (again) {			dpr->ToHyInt = 1;			dpr->ToPcInt = 1;	/* interrupt to E1 for all cards */		} else			card->hw_lock = 0;	/* free hardware again */	} while (again);	/* until nothing more to do */	restore_flags(flags);}				/* ergo_irq_bh *//*********************************************************//* stop the card (hardware reset) and disable interrupts *//*********************************************************/static voidergo_stopcard(hysdn_card * card){	ulong flags;	uchar val;	hysdn_net_release(card);	/* first release the net device if existing */#ifdef CONFIG_HYSDN_CAPI	hycapi_capi_stop(card);#endif /* CONFIG_HYSDN_CAPI */	save_flags(flags);	cli();	val = bytein(card->iobase + PCI9050_INTR_REG);	/* get actual value */	val &= ~(PCI9050_INTR_REG_ENPCI | PCI9050_INTR_REG_EN1);	/* mask irq */	byteout(card->iobase + PCI9050_INTR_REG, val);	card->irq_enabled = 0;	byteout(card->iobase + PCI9050_USER_IO, PCI9050_E1_RESET);	/* reset E1 processor */	card->state = CARD_STATE_UNUSED;	card->err_log_state = ERRLOG_STATE_OFF;		/* currently no log active */	restore_flags(flags);}				/* ergo_stopcard *//**************************************************************************//* enable or disable the cards error log. The event is queued if possible *//**************************************************************************/static voidergo_set_errlog_state(hysdn_card * card, int on){	ulong flags;	if (card->state != CARD_STATE_RUN) {		card->err_log_state = ERRLOG_STATE_OFF;		/* must be off */		return;	}	save_flags(flags);	cli();	if (((card->err_log_state == ERRLOG_STATE_OFF) && !on) ||	    ((card->err_log_state == ERRLOG_STATE_ON) && on)) {		restore_flags(flags);		return;		/* nothing to do */	}	if (on)		card->err_log_state = ERRLOG_STATE_START;	/* request start */	else		card->err_log_state = ERRLOG_STATE_STOP;	/* request stop */	restore_flags(flags);	schedule_work(&card->irq_queue);}				/* ergo_set_errlog_state *//******************************************//* test the cards RAM and return 0 if ok. *//******************************************/static const char TestText[36] = "This Message is filler, why read it";static intergo_testram(hysdn_card * card){	tErgDpram *dpr = card->dpram;	memset(dpr->TrapTable, 0, sizeof(dpr->TrapTable));	/* clear all Traps */	dpr->ToHyInt = 1;	/* E1 INTR state forced */	memcpy(&dpr->ToHyBuf[ERG_TO_HY_BUF_SIZE - sizeof(TestText)], TestText,	       sizeof(TestText));	if (memcmp(&dpr->ToHyBuf[ERG_TO_HY_BUF_SIZE - sizeof(TestText)], TestText,		   sizeof(TestText)))		return (-1);	memcpy(&dpr->ToPcBuf[ERG_TO_PC_BUF_SIZE - sizeof(TestText)], TestText,	       sizeof(TestText));	if (memcmp(&dpr->ToPcBuf[ERG_TO_PC_BUF_SIZE - sizeof(TestText)], TestText,		   sizeof(TestText)))		return (-1);	return (0);}				/* ergo_testram *//*****************************************************************************//* this function is intended to write stage 1 boot image to the cards buffer *//* this is done in two steps. First the 1024 hi-words are written (offs=0),  *//* then the 1024 lo-bytes are written. The remaining DPRAM is cleared, the   *//* PCI-write-buffers flushed and the card is taken out of reset.             *//* The function then waits for a reaction of the E1 processor or a timeout.  *//* Negative return values are interpreted as errors.                         *//*****************************************************************************/static intergo_writebootimg(struct HYSDN_CARD *card, uchar * buf, ulong offs){	uchar *dst;	tErgDpram *dpram;	int cnt = (BOOT_IMG_SIZE >> 2);		/* number of words to move and swap (byte order!) */		if (card->debug_flags & LOG_POF_CARD)		hysdn_addlog(card, "ERGO: write bootldr offs=0x%lx ", offs);	dst = card->dpram;	/* pointer to start of DPRAM */

⌨️ 快捷键说明

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