📄 farsync.c
字号:
}}static voiddo_bottom_half_rx(struct fst_card_info *card){ struct fst_port_info *port; int pi; int rx_count = 0; /* Check for rx completions on all ports on this card */ dbg(DBG_RX, "do_bottom_half_rx\n"); for (pi = 0, port = card->ports; pi < card->nports; pi++, port++) { if (!port->run) continue; while (!(FST_RDB(card, rxDescrRing[pi][port->rxpos].bits) & DMA_OWN) && !(card->dmarx_in_progress)) { if (rx_count > fst_max_reads) { /* * Don't spend forever in receive processing * Schedule another event */ fst_q_work_item(&fst_work_intq, card->card_no); tasklet_schedule(&fst_int_task); break; /* Leave the loop */ } fst_intr_rx(card, port); rx_count++; } }}/* * The interrupt service routine * Dev_id is our fst_card_info pointer */irqreturn_tfst_intr(int irq, void *dev_id, struct pt_regs *regs){ struct fst_card_info *card; struct fst_port_info *port; int rdidx; /* Event buffer indices */ int wridx; int event; /* Actual event for processing */ unsigned int dma_intcsr = 0; unsigned int do_card_interrupt; unsigned int int_retry_count; if ((card = dev_id) == NULL) { dbg(DBG_INTR, "intr: spurious %d\n", irq); return IRQ_NONE; } /* * Check to see if the interrupt was for this card * return if not * Note that the call to clear the interrupt is important */ dbg(DBG_INTR, "intr: %d %p\n", irq, card); if (card->state != FST_RUNNING) { printk_err ("Interrupt received for card %d in a non running state (%d)\n", card->card_no, card->state); /* * It is possible to really be running, i.e. we have re-loaded * a running card * Clear and reprime the interrupt source */ fst_clear_intr(card); return IRQ_HANDLED; } /* Clear and reprime the interrupt source */ fst_clear_intr(card); /* * Is the interrupt for this card (handshake == 1) */ do_card_interrupt = 0; if (FST_RDB(card, interruptHandshake) == 1) { do_card_interrupt += FST_CARD_INT; /* Set the software acknowledge */ FST_WRB(card, interruptHandshake, 0xEE); } if (card->family == FST_FAMILY_TXU) { /* * Is it a DMA Interrupt */ dma_intcsr = inl(card->pci_conf + INTCSR_9054); if (dma_intcsr & 0x00200000) { /* * DMA Channel 0 (Rx transfer complete) */ dbg(DBG_RX, "DMA Rx xfer complete\n"); outb(0x8, card->pci_conf + DMACSR0); fst_rx_dma_complete(card, card->dma_port_rx, card->dma_len_rx, card->dma_skb_rx, card->dma_rxpos); card->dmarx_in_progress = 0; do_card_interrupt += FST_RX_DMA_INT; } if (dma_intcsr & 0x00400000) { /* * DMA Channel 1 (Tx transfer complete) */ dbg(DBG_TX, "DMA Tx xfer complete\n"); outb(0x8, card->pci_conf + DMACSR1); fst_tx_dma_complete(card, card->dma_port_tx, card->dma_len_tx, card->dma_txpos); card->dmatx_in_progress = 0; do_card_interrupt += FST_TX_DMA_INT; } } /* * Have we been missing Interrupts */ int_retry_count = FST_RDL(card, interruptRetryCount); if (int_retry_count) { dbg(DBG_ASS, "Card %d int_retry_count is %d\n", card->card_no, int_retry_count); FST_WRL(card, interruptRetryCount, 0); } if (!do_card_interrupt) { return IRQ_HANDLED; } /* Scehdule the bottom half of the ISR */ fst_q_work_item(&fst_work_intq, card->card_no); tasklet_schedule(&fst_int_task); /* Drain the event queue */ rdidx = FST_RDB(card, interruptEvent.rdindex) & 0x1f; wridx = FST_RDB(card, interruptEvent.wrindex) & 0x1f; while (rdidx != wridx) { event = FST_RDB(card, interruptEvent.evntbuff[rdidx]); port = &card->ports[event & 0x03]; dbg(DBG_INTR, "Processing Interrupt event: %x\n", event); switch (event) { case TE1_ALMA: dbg(DBG_INTR, "TE1 Alarm intr\n"); if (port->run) fst_intr_te1_alarm(card, port); break; case CTLA_CHG: case CTLB_CHG: case CTLC_CHG: case CTLD_CHG: if (port->run) fst_intr_ctlchg(card, port); break; case ABTA_SENT: case ABTB_SENT: case ABTC_SENT: case ABTD_SENT: dbg(DBG_TX, "Abort complete port %d\n", port->index); break; case TXA_UNDF: case TXB_UNDF: case TXC_UNDF: case TXD_UNDF: /* Difficult to see how we'd get this given that we * always load up the entire packet for DMA. */ dbg(DBG_TX, "Tx underflow port %d\n", port->index); hdlc_stats(port_to_dev(port))->tx_errors++; hdlc_stats(port_to_dev(port))->tx_fifo_errors++; dbg(DBG_ASS, "Tx underflow on card %d port %d\n", card->card_no, port->index); break; case INIT_CPLT: dbg(DBG_INIT, "Card init OK intr\n"); break; case INIT_FAIL: dbg(DBG_INIT, "Card init FAILED intr\n"); card->state = FST_IFAILED; break; default: printk_err("intr: unknown card event %d. ignored\n", event); break; } /* Bump and wrap the index */ if (++rdidx >= MAX_CIRBUFF) rdidx = 0; } FST_WRB(card, interruptEvent.rdindex, rdidx); return IRQ_HANDLED;}/* Check that the shared memory configuration is one that we can handle * and that some basic parameters are correct */static voidcheck_started_ok(struct fst_card_info *card){ int i; /* Check structure version and end marker */ if (FST_RDW(card, smcVersion) != SMC_VERSION) { printk_err("Bad shared memory version %d expected %d\n", FST_RDW(card, smcVersion), SMC_VERSION); card->state = FST_BADVERSION; return; } if (FST_RDL(card, endOfSmcSignature) != END_SIG) { printk_err("Missing shared memory signature\n"); card->state = FST_BADVERSION; return; } /* Firmware status flag, 0x00 = initialising, 0x01 = OK, 0xFF = fail */ if ((i = FST_RDB(card, taskStatus)) == 0x01) { card->state = FST_RUNNING; } else if (i == 0xFF) { printk_err("Firmware initialisation failed. Card halted\n"); card->state = FST_HALTED; return; } else if (i != 0x00) { printk_err("Unknown firmware status 0x%x\n", i); card->state = FST_HALTED; return; } /* Finally check the number of ports reported by firmware against the * number we assumed at card detection. Should never happen with * existing firmware etc so we just report it for the moment. */ if (FST_RDL(card, numberOfPorts) != card->nports) { printk_warn("Port count mismatch on card %d." " Firmware thinks %d we say %d\n", card->card_no, FST_RDL(card, numberOfPorts), card->nports); }}static intset_conf_from_info(struct fst_card_info *card, struct fst_port_info *port, struct fstioc_info *info){ int err; unsigned char my_framing; /* Set things according to the user set valid flags * Several of the old options have been invalidated/replaced by the * generic hdlc package. */ err = 0; if (info->valid & FSTVAL_PROTO) { if (info->proto == FST_RAW) port->mode = FST_RAW; else port->mode = FST_GEN_HDLC; } if (info->valid & FSTVAL_CABLE) err = -EINVAL; if (info->valid & FSTVAL_SPEED) err = -EINVAL; if (info->valid & FSTVAL_PHASE) FST_WRB(card, portConfig[port->index].invertClock, info->invertClock); if (info->valid & FSTVAL_MODE) FST_WRW(card, cardMode, info->cardMode); if (info->valid & FSTVAL_TE1) { FST_WRL(card, suConfig.dataRate, info->lineSpeed); FST_WRB(card, suConfig.clocking, info->clockSource); my_framing = FRAMING_E1; if (info->framing == E1) my_framing = FRAMING_E1; if (info->framing == T1) my_framing = FRAMING_T1; if (info->framing == J1) my_framing = FRAMING_J1; FST_WRB(card, suConfig.framing, my_framing); FST_WRB(card, suConfig.structure, info->structure); FST_WRB(card, suConfig.interface, info->interface); FST_WRB(card, suConfig.coding, info->coding); FST_WRB(card, suConfig.lineBuildOut, info->lineBuildOut); FST_WRB(card, suConfig.equalizer, info->equalizer); FST_WRB(card, suConfig.transparentMode, info->transparentMode); FST_WRB(card, suConfig.loopMode, info->loopMode); FST_WRB(card, suConfig.range, info->range); FST_WRB(card, suConfig.txBufferMode, info->txBufferMode); FST_WRB(card, suConfig.rxBufferMode, info->rxBufferMode); FST_WRB(card, suConfig.startingSlot, info->startingSlot); FST_WRB(card, suConfig.losThreshold, info->losThreshold); if (info->idleCode) FST_WRB(card, suConfig.enableIdleCode, 1); else FST_WRB(card, suConfig.enableIdleCode, 0); FST_WRB(card, suConfig.idleCode, info->idleCode);#if FST_DEBUG if (info->valid & FSTVAL_TE1) { printk("Setting TE1 data\n"); printk("Line Speed = %d\n", info->lineSpeed); printk("Start slot = %d\n", info->startingSlot); printk("Clock source = %d\n", info->clockSource); printk("Framing = %d\n", my_framing); printk("Structure = %d\n", info->structure); printk("interface = %d\n", info->interface); printk("Coding = %d\n", info->coding); printk("Line build out = %d\n", info->lineBuildOut); printk("Equaliser = %d\n", info->equalizer); printk("Transparent mode = %d\n", info->transparentMode); printk("Loop mode = %d\n", info->loopMode); printk("Range = %d\n", info->range); printk("Tx Buffer mode = %d\n", info->txBufferMode); printk("Rx Buffer mode = %d\n", info->rxBufferMode); printk("LOS Threshold = %d\n", info->losThreshold); printk("Idle Code = %d\n", info->idleCode); }#endif }#if FST_DEBUG if (info->valid & FSTVAL_DEBUG) { fst_debug_mask = info->debug; }#endif return err;}static voidgather_conf_info(struct fst_card_info *card, struct fst_port_info *port, struct fstioc_info *info){ int i; memset(info, 0, sizeof (struct fstioc_info)); i = port->index; info->kernelVersion = LINUX_VERSION_CODE; info->nports = card->nports; info->type = card->type; info->state = card->state; info->proto = FST_GEN_HDLC; info->index = i;#if FST_DEBUG info->debug = fst_debug_mask;#endif /* Only mark information as valid if card is running. * Copy the data anyway in case it is useful for diagnostics */ info->valid = ((card->state == FST_RUNNING) ? FSTVAL_ALL : FSTVAL_CARD)#if FST_DEBUG | FSTVAL_DEBUG#endif ; info->lineInterface = FST_RDW(card, portConfig[i].lineInterface); info->internalClock = FST_RDB(card, portConfig[i].internalClock); info->lineSpeed = FST_RDL(card, portConfig[i].lineSpeed); info->invertClock = FST_RDB(card, portConfig[i].invertClock); info->v24IpSts = FST_RDL(card, v24IpSts[i]); info->v24OpSts = FST_RDL(card, v24OpSts[i]); info->clockStatus = FST_RDW(card, clockStatus[i]); info->cableStatus = FST_RDW(card, cableStatus); info->cardMode = FST_RDW(card, cardMode); info->smcFirmwareVersion = FST_RDL(card, smcFirmwareVersion); /* * The T2U can report cable presence for both A or B * in bits 0 and 1 of cableStatus. See which port we are and * do the mapping. */ if (card->family == FST_FAMILY_TXU) { if (port->index == 0) { /* * Port A */ info->cableStatus = info->cableStatus & 1; } else { /* * Port B */ info->cableStatus = info->cableStatus >> 1; info->cableStatus = info->cableStatus & 1; } } /* * Some additional bits if we are TE1 */ if (card->type == FST_TYPE_TE1) { info->lineSpeed = FST_RDL(card, suConfig.dataRate); info->clockSource = FST_RDB(card, suConfig.clocking); info->framing = FST_RDB(card, suConfig.framing); info->structure = FST_RDB(card, suConfig.structure); info->interface = FST_RDB(card, suConfig.interface); info->coding = FST_RDB(card, suConfig.coding); info->lineBuildOut = FST_RDB(card, suConfig.lineBuildOut); info->equalizer = FST_RDB(card, suConfig.equalizer); info->loopMode = FST_RDB(card, suConfig.loopMode); info->range = FST_RDB(card, suConfig.range); info->txBufferMode = FST_RDB(card, suConfig.txBufferMode); info->rxBufferMode = FST_RDB(card, suConfig.rxBufferMode); info->startingSlot = FST_RDB(card, suConfig.startingSlot); info->losThreshold = FST_RDB(card, suConfig.losThreshold); if (FST_RDB(card, suConfig.enableIdleCode)) info->idleCode = FST_RDB(card, suConfig.idleCode); else info->idleCode = 0; info->receiveBufferDelay = FST_RDL(card, suStatus.receiveBufferDelay); info->framingErrorCount = FST_RDL(card, suStatus.framingErrorCount); info->codeViolationCount = FST_RDL(card, suStatus.codeViolationCount); info->crcErrorCount = FST_RDL(card, suStatus.crcErrorCount); info->lineAttenuation = FST_RDL(card, suStatus.lineAttenuation); info->lossOfSignal = FST_RDB(card, suStatus.lossOfSignal); info->receiveRemoteAlarm = FST_RDB(card, suStatus.receiveRemoteAlarm); info->alarmIndicationSignal = FST_RDB(card, suStatus.alarmIndicationSignal); }}static intfst_set_iface(struct fst_card_info *card, struct fst_port_info *port, struct ifreq *ifr){ sync_serial_settings sync; int i; if (ifr->ifr_settings.size != sizeof (sync)) { return -ENOMEM; } if (copy_from_user (&sync, ifr->ifr_settings.ifs_ifsu.sync, sizeof (sync))) { return -EFAULT; } if (sync.loopback) return -EINVAL; i = port->index; switch (ifr->ifr_settings.type) { case IF_IFACE_V35: FST_WRW(card, portConfig[i].lineInterface, V35); port->hwif = V35; break; case IF_IFACE_V24: FST_WRW(card, portConfig[i].lineInterface, V24); port->hwif = V24; break; case IF_IFACE_X21: FST_WRW(card, portConfig[i].lineInterface, X21); port->hwif = X21; break; case IF_IFACE_X21D: FST_WRW(card, portConfig[i].lineInterface, X21D); port->hwif = X21D; break; case IF_IFACE_T1: FST_WRW(card, portConfig[i].lineInterface, T1); port->hwif = T1; break; case IF_IFACE_E1: FST_WRW(card, portConfig[i].lineInterface, E1); port->hwif = E1; break; case IF_IFACE_SYNC_SERIAL: break; default:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -