📄 boardergo.c
字号:
/* $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 + -