📄 comx-hw-munich.c
字号:
{ u8 *lbi = slicecom_boards[boardnum].lbi; spin_lock_irqsave(&mister_lock, flags); slicecom_boards[boardnum].framing = value; switch (value) { case SLICECOM_FRAMING_CRC4: writeb(readb(lbi + FMR1) | 8, lbi + FMR1); writeb((readb(lbi + FMR2) & 0x3f) | 0x80, lbi + FMR2); break; case SLICECOM_FRAMING_NO_CRC4: writeb(readb(lbi + FMR1) & 0xf7, lbi + FMR1); writeb(readb(lbi + FMR2) & 0x3f, lbi + FMR2); break; default: printk("slicecom: board %d: unhandled " FILENAME_FRAMING " value %d\n", boardnum, value); } spin_unlock_irqrestore(&mister_lock, flags);}/* * Set PCM linecode - /proc/comx/comx0/linecode */void slicecom_set_linecode(int boardnum, int value){ u8 *lbi = slicecom_boards[boardnum].lbi; spin_lock_irqsave(&mister_lock, flags); slicecom_boards[boardnum].linecode = value; switch (value) { case SLICECOM_LINECODE_HDB3: writeb(readb(lbi + FMR0) | 0xf0, lbi + FMR0); break; case SLICECOM_LINECODE_AMI: writeb((readb(lbi + FMR0) & 0x0f) | 0xa0, lbi + FMR0); break; default: printk("slicecom: board %d: unhandled " FILENAME_LINECODE " value %d\n", boardnum, value); } spin_unlock_irqrestore(&mister_lock, flags);}/* * Set PCM clock source - /proc/comx/comx0/clock_source */void slicecom_set_clock_source(int boardnum, int value){ u8 *lbi = slicecom_boards[boardnum].lbi; spin_lock_irqsave(&mister_lock, flags); slicecom_boards[boardnum].clock_source = value; switch (value) { case SLICECOM_CLOCK_SOURCE_LINE: writeb(readb(lbi + LIM0) & ~1, lbi + LIM0); break; case SLICECOM_CLOCK_SOURCE_INTERNAL: writeb(readb(lbi + LIM0) | 1, lbi + LIM0); break; default: printk("slicecom: board %d: unhandled " FILENAME_CLOCK_SOURCE " value %d\n", boardnum, value); } spin_unlock_irqrestore(&mister_lock, flags);}/* * Set loopbacks - /proc/comx/comx0/loopback */void slicecom_set_loopback(int boardnum, int value){ u8 *lbi = slicecom_boards[boardnum].lbi; spin_lock_irqsave(&mister_lock, flags); slicecom_boards[boardnum].loopback = value; switch (value) { case SLICECOM_LOOPBACK_NONE: writeb(readb(lbi + LIM0) & ~2, lbi + LIM0); /* Local Loop OFF */ writeb(readb(lbi + LIM1) & ~2, lbi + LIM1); /* Remote Loop OFF */ break; case SLICECOM_LOOPBACK_LOCAL: writeb(readb(lbi + LIM1) & ~2, lbi + LIM1); /* Remote Loop OFF */ writeb(readb(lbi + LIM0) | 2, lbi + LIM0); /* Local Loop ON */ break; case SLICECOM_LOOPBACK_REMOTE: writeb(readb(lbi + LIM0) & ~2, lbi + LIM0); /* Local Loop OFF */ writeb(readb(lbi + LIM1) | 2, lbi + LIM1); /* Remote Loop ON */ break; default: printk("slicecom: board %d: unhandled " FILENAME_LOOPBACK " value %d\n", boardnum, value); } spin_unlock_irqrestore(&mister_lock, flags);}/* * Update E1 line status LEDs on the adapter */void slicecom_update_leds(munich_board_t * board){ u32 *bar1 = board->bar1; u8 *lbi = board->lbi; u8 frs0; u32 leds; int i; spin_lock_irqsave(&mister_lock, flags); leds = 0; frs0 = readb(lbi + FRS0); /* FRS0 bits described on page 137 */ if (!(frs0 & 0xa0)) { leds |= 0x2000; /* Green LED: Input signal seems to be OK, no LOS, no LFA */ if (frs0 & 0x10) leds |= 0x8000; /* Red LED: Receiving Remote Alarm */ } writel(leds, MUNICH_VIRT(GPDATA)); if (leds == 0x2000 && !board->lineup) { /* line up */ board->lineup = 1; for (i = 0; i < 32; i++) { if (board->twins[i] && (board->twins[i]->flags & IFF_RUNNING)) { struct comx_channel *ch = board->twins[i]->priv; if (!test_and_set_bit(0, &ch->lineup_pending)) { ch->lineup_timer.function = comx_lineup_func; ch->lineup_timer.data = (unsigned long)board->twins[i]; ch->lineup_timer.expires = jiffies + HZ * ch->lineup_delay; add_timer(&ch->lineup_timer); } } } } else if (leds != 0x2000 && board->lineup) { /* line down */ board->lineup = 0; for (i = 0; i < 32; i++) if (board->twins[i] && (board->twins[i]->flags & IFF_RUNNING)) { struct comx_channel *ch = board->twins[i]->priv; if (test_and_clear_bit(0, &ch->lineup_pending)) del_timer(&ch->lineup_timer); else if (ch->line_status & LINE_UP) { ch->line_status &= ~LINE_UP; if (ch->LINE_status) ch->LINE_status(board->twins[i], ch->line_status); } } } spin_unlock_irqrestore(&mister_lock, flags);}/* * This function gets called every second when the FALC issues the interrupt. * Hardware counters contain error counts for last 1-second time interval. * We add them to the global counters here. * Read rfc2495 to understand this. */void slicecom_update_line_counters(munich_board_t * board){ e1_stats_t *curr_int = &board->intervals[board->current_interval]; u8 *lbi = board->lbi; unsigned framing_errors, code_violations, path_code_violations, crc4_errors, e_bit_errors; unsigned slip_detected, /* this one has logical value, not the number of slips! */ out_of_frame_defect, /* logical value */ ais_defect, /* logical value */ errored_sec, bursty_err_sec, severely_err_sec = 0, failure_sec; u8 isr2, isr3, isr5, frs0; spin_lock_irqsave(&mister_lock, flags); isr2 = readb(lbi + ISR2); /* ISR0-5 described on page 156 */ isr3 = readb(lbi + ISR3); isr5 = readb(lbi + ISR5); frs0 = readb(lbi + FRS0); /* FRS0 described on page 137 */ /* Error Events: */ code_violations = readb(lbi + CVCL) + (readb(lbi + CVCH) << 8); framing_errors = readb(lbi + FECL) + (readb(lbi + FECH) << 8); crc4_errors = readb(lbi + CEC1L) + (readb(lbi + CEC1H) << 8); e_bit_errors = readb(lbi + EBCL) + (readb(lbi + EBCH) << 8); slip_detected = isr3 & (ISR3_RSN | ISR3_RSP); path_code_violations = framing_errors + crc4_errors; curr_int->line_code_violations += code_violations; curr_int->path_code_violations += path_code_violations; curr_int->e_bit_errors += e_bit_errors; /* Performance Defects: */ /* there was an LFA in the last second, but maybe disappeared: */ out_of_frame_defect = (isr2 & ISR2_LFA) || (frs0 & FRS0_LFA); /* there was an AIS in the last second, but maybe disappeared: */ ais_defect = (isr2 & ISR2_AIS) || (frs0 & FRS0_AIS); /* Performance Parameters: */ if (out_of_frame_defect) curr_int->fr_loss_secs++; if (code_violations) curr_int->line_err_secs++; errored_sec = ((board->framing == SLICECOM_FRAMING_NO_CRC4) && (code_violations)) || path_code_violations || out_of_frame_defect || slip_detected || ais_defect; bursty_err_sec = !out_of_frame_defect && !ais_defect && (path_code_violations > 1) && (path_code_violations < 320); switch (board->framing) { case SLICECOM_FRAMING_CRC4: severely_err_sec = out_of_frame_defect || (path_code_violations >= 832); break; case SLICECOM_FRAMING_NO_CRC4: severely_err_sec = (code_violations >= 2048); break; } /* * failure_sec: true if there was a condition leading to a failure * (and leading to unavailable state) in this second: */ failure_sec = (isr2 & ISR2_RA) || (frs0 & FRS0_RRA) /* Remote/Far End/Distant Alarm Failure */ || ais_defect || out_of_frame_defect /* AIS or LOF Failure */ || (isr2 & ISR2_LOS) || (frs0 & FRS0_LOS) /* Loss Of Signal Failure */ || (board->loopback != SLICECOM_LOOPBACK_NONE); /* Loopback has been set */ if (board->is_unavailable) { if (severely_err_sec) board->no_ses_seconds = 0; else board->no_ses_seconds++; if ((board->no_ses_seconds >= 10) && !failure_sec) { board->is_unavailable = 0; board->ses_seconds = 0; board->no_ses_seconds = 0; } } else { if (severely_err_sec) board->ses_seconds++; else board->ses_seconds = 0; if ((board->ses_seconds >= 10) || failure_sec) { board->is_unavailable = 1; board->ses_seconds = 0; board->no_ses_seconds = 0; } } if (board->is_unavailable) curr_int->unavail_secs++; else { if (slip_detected) curr_int->slip_secs++; curr_int->errored_secs += errored_sec; curr_int->bursty_err_secs += bursty_err_sec; curr_int->severely_err_secs += severely_err_sec; } /* the RFC does not say clearly which errors to count here, we try to count bit errors */ if (!board->is_unavailable && !severely_err_sec) { board->deg_cumulated_errors += code_violations; board->deg_elapsed_seconds++; if (board->deg_elapsed_seconds >= 60) { if (board->deg_cumulated_errors >= 123) curr_int->degraded_mins++; board->deg_cumulated_errors = 0; board->deg_elapsed_seconds = 0; } } board->elapsed_seconds++; if (board->elapsed_seconds >= 900) { board->current_interval = (board->current_interval + 1) % SLICECOM_BOARD_INTERVALS_SIZE; memset((void *)&board->intervals[board->current_interval], 0, sizeof(e1_stats_t)); board->elapsed_seconds = 0; } spin_unlock_irqrestore(&mister_lock, flags);}static void pcicom_modemline(unsigned long b){ munich_board_t *board = (munich_board_t *) b; struct net_device *dev = board->twins[0]; struct comx_channel *ch = dev->priv; unsigned long regs; regs = readl((void *)(&board->bar1[GPDATA])); if ((ch->line_status & LINE_UP) && (regs & 0x0800)) { ch->line_status &= ~LINE_UP; board->lineup = 0; if (ch->LINE_status) { ch->LINE_status(dev, ch->line_status); } } if (!(ch->line_status & LINE_UP) && !(regs & 0x0800)) { ch->line_status |= LINE_UP; board->lineup = 1; if (ch->LINE_status) { ch->LINE_status(dev, ch->line_status); } } mod_timer((struct timer_list *)&board->modemline_timer, jiffies + HZ);}/* * Is it possible to transmit ? * Called (may be called) by the protocol layer */static int MUNICH_txe(struct net_device *dev){ struct comx_channel *ch = dev->priv; struct slicecom_privdata *hw = ch->HW_privdata; return (hw->busy < TX_DESC_MAX - 1);}/* * Hw probe function. Detects all the boards in the system, * and fills up slicecom_boards[] and pcicom_boards[] * Returns 0 on success. * We do not disable interrupts! */static int munich_probe(void){ struct pci_dev *pci; int boardnum; int slicecom_boardnum; int pcicom_boardnum; u32 *bar1; u8 *lbi; munich_board_t *board; for (boardnum = 0; boardnum < MAX_BOARDS; boardnum++) { pcicom_boards[boardnum].pci = 0; pcicom_boards[boardnum].bar1 = 0; pcicom_boards[boardnum].lbi = 0; slicecom_boards[boardnum].pci = 0; slicecom_boards[boardnum].bar1 = 0; slicecom_boards[boardnum].lbi = 0; } pci = NULL; board = NULL; slicecom_boardnum = 0; pcicom_boardnum = 0; for (boardnum = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -