📄 comx-hw-munich.c
字号:
boardnum < MAX_BOARDS && (pci = pci_find_device(PCI_VENDOR_ID_SIEMENS, PCI_DEVICE_ID_SIEMENS_MUNICH32X, pci)); boardnum++) { if (pci_enable_device(pci)) continue; printk("munich_probe: munich chip found, IRQ %d\n", pci->irq);#if (LINUX_VERSION_CODE < 0x02030d) bar1 = ioremap_nocache(pci->base_address[0], 0x100); lbi = ioremap_nocache(pci->base_address[1], 0x100);#else bar1 = ioremap_nocache(pci->resource[0].start, 0x100); lbi = ioremap_nocache(pci->resource[1].start, 0x100);#endif if (bar1 && lbi) { pci_write_config_dword(pci, MUNICH_PCI_PCIRES, 0xe0000); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); pci_write_config_dword(pci, MUNICH_PCI_PCIRES, 0); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); /* check the type of the card */ writel(LREG0_MAGIC, MUNICH_VIRT(LREG0)); writel(LREG1_MAGIC, MUNICH_VIRT(LREG1)); writel(LREG2_MAGIC, MUNICH_VIRT(LREG2)); writel(LREG3_MAGIC, MUNICH_VIRT(LREG3)); writel(LREG4_MAGIC, MUNICH_VIRT(LREG4)); writel(LREG5_MAGIC, MUNICH_VIRT(LREG5)); writel(LCONF_MAGIC2,MUNICH_VIRT(LCONF)); /* enable the DMSM */ if ((readb(lbi + VSTR) == 0x13) || (readb(lbi + VSTR) == 0x10)) { board = slicecom_boards + slicecom_boardnum; sprintf((char *)board->devname, "slicecom%d", slicecom_boardnum); board->isx21 = 0; slicecom_boardnum++; } else if ((readb(lbi + VSTR) == 0x6) || (readb(lbi + GIS) == 0x6)) { board = pcicom_boards + pcicom_boardnum; sprintf((char *)board->devname, "pcicom%d", pcicom_boardnum); board->isx21 = 1; pcicom_boardnum++; } if (board) { printk("munich_probe: %s board found\n", board->devname); writel(LCONF_MAGIC1, MUNICH_VIRT(LCONF)); /* reset the DMSM */ board->pci = pci; board->bar1 = bar1; board->lbi = lbi; board->framing = SLICECOM_FRAMING_DEFAULT; board->linecode = SLICECOM_LINECODE_DEFAULT; board->clock_source = SLICECOM_CLOCK_SOURCE_DEFAULT; board->loopback = SLICECOM_LOOPBACK_DEFAULT; SET_MODULE_OWNER(board); } else { printk("munich_probe: Board error, VSTR: %02X\n", readb(lbi + VSTR)); iounmap((void *)bar1); iounmap((void *)lbi); } } else { printk("munich_probe: ioremap() failed, not enabling this board!\n"); /* .pci = NULL, so the MUNICH_open will not try to open it */ if (bar1) iounmap((void *)bar1); if (lbi) iounmap((void *)lbi); } } if (!pci && !boardnum) { printk("munich_probe: no PCI present!\n"); return -ENODEV; } if (pcicom_boardnum + slicecom_boardnum == 0) { printk ("munich_probe: Couldn't find any munich board: vendor:device %x:%x not found\n", PCI_VENDOR_ID_SIEMENS, PCI_DEVICE_ID_SIEMENS_MUNICH32X); return -ENODEV; } /* Found some */ if (pcicom_boardnum) printk("%d pcicom board(s) found.\n", pcicom_boardnum); if (slicecom_boardnum) printk("%d slicecom board(s) found.\n", slicecom_boardnum); return 0;}/* * Reset the hardware. Get called only from within this module if needed. */#if 0static int slicecom_reset(struct net_device *dev){ struct comx_channel *ch = dev->priv; printk("slicecom_reset: resetting the hardware\n"); /* Begin to reset the hardware */ if (ch->HW_set_clock) ch->HW_set_clock(dev); /* And finish it */ return 0;}#endif/* * Transmit a packet. * Called by the protocol layer * Return values: * FRAME_ACCEPTED: frame is being transmited, transmitter is busy * FRAME_QUEUED: frame is being transmitted, there's more room in * the transmitter for additional packet(s) * FRAME_ERROR: * FRAME_DROPPED: there was some error */static int MUNICH_send_packet(struct net_device *dev, struct sk_buff *skb){ struct comx_channel *ch = (struct comx_channel *)dev->priv; struct slicecom_privdata *hw = ch->HW_privdata; /* Send it to the debug facility too if needed: */ if (ch->debug_flags & DEBUG_HW_TX) comx_debug_bytes(dev, skb->data, skb->len, "MUNICH_send_packet"); /* If the line is inactive, don't accept: */ /* TODO: atgondolni hogy mi is legyen itt */ /* if (!(ch->line_status & LINE_UP)) return FRAME_DROPPED; */ /* More check, to be sure: */ if (skb->len > TXBUFFER_SIZE) { ch->stats.tx_errors++; kfree_skb(skb); return FRAME_ERROR; } /* Maybe you have to disable irq's while programming the hw: */ spin_lock_irqsave(&mister_lock, flags); /* And more check: */ if (hw->busy >= TX_DESC_MAX - 1) { printk(KERN_ERR "%s: Transmitter called while busy... dropping frame, busy = %d\n", dev->name, hw->busy); spin_unlock_irqrestore(&mister_lock, flags); kfree_skb(skb); return FRAME_DROPPED; } if (hw->busy >= 0) hw->tx_ring_hist[hw->busy]++; /* DELL: */ else printk("slicecom: %s: FATAL: busy = %d\n", dev->name, hw->busy);// /* DEL: */// printk("slicecom: %s: _send_packet called, busy = %d\n", dev->name, hw->busy ); /* Packet can go, update stats: */ ch->stats.tx_packets++; ch->stats.tx_bytes += skb->len; /* Pass the packet to the HW: */ /* Step forward with the transmit descriptors: */ hw->tx_desc_ptr = (hw->tx_desc_ptr + 1) % TX_DESC_MAX; memcpy(&(hw->tx_data[hw->tx_desc_ptr][0]), skb->data, skb->len); hw->tx_desc[hw->tx_desc_ptr].no = skb->len; /* We don't issue any command, just step with the HOLD bit */ hw->tx_desc[hw->tx_desc_ptr].hold = 1; hw->tx_desc[(hw->tx_desc_ptr + TX_DESC_MAX - 1) % TX_DESC_MAX].hold = 0;#ifdef COMX_NEW dev_kfree_skb(skb);#endif /* csomag kerult a Tx ringbe: */ hw->busy++; /* Report it: */ if (ch->debug_flags & DEBUG_HW_TX) comx_debug(dev, "%s: MUNICH_send_packet was successful\n\n", dev->name); if (hw->busy >= TX_DESC_MAX - 1) { spin_unlock_irqrestore(&mister_lock, flags); return FRAME_ACCEPTED; } spin_unlock_irqrestore(&mister_lock, flags); /* All done */ return FRAME_QUEUED;}/* * Interrupt handler routine. * Called by the Linux kernel. * BEWARE! The interrupts are enabled on the call! */static void MUNICH_interrupt(int irq, void *dev_id, struct pt_regs *regs){ struct sk_buff *skb; int length; int rx_status; int work; /* hany esemenyt kezeltem mar le */ u32 *bar1; u8 *lbi; u32 stat, /* az esemenyek, amiket a ebben a loop korben le kell meg kezelni */ race_stat = 0, /* race eseten ebben uzenek magamnak hogy mit kell meg lekezelni */ ack; /* ezt fogom a vegen a STAT-ba irni, kiveszek belole 1-1 bitet ha */ /* az adott dolgot nem kell ack-olni mert volt vele munkam, es */ /* legjobb ha visszaterek ide megegyszer */ munich_intq_t int_info; struct net_device *dev; struct comx_channel *ch; struct slicecom_privdata *hw; munich_board_t *board = (munich_board_t *) dev_id; int channel; // , boardnum = (int)dev_id; // board = munich_boards + boardnum; bar1 = board->bar1; lbi = board->lbi; // Do not uncomment this under heavy load! :-> // printk("MUNICH_interrupt: masked STAT=0x%08x, tiq=0x%08x, riq=0x%08x, piq=0x%08x\n", stat, board->tiq[0].all, board->riq[0].all, board->piq[0].all ); for (work = 0; (stat = (race_stat | (readl(MUNICH_VIRT(STAT)) & ~STAT_NOT_HANDLED_BY_INTERRUPT))) && (work < MAX_WORK - 1); work++) { ack = stat & (STAT_PRI | STAT_PTI | STAT_LBII); /* Handle the interrupt information in the Rx queue. We don't really trust */ /* info from this queue, because it can be overflowed, so later check */ /* every Rx ring for received packets. But there are some errors which can't */ /* be counted from the Rx rings, so we parse it. */ int_info = board->riq[board->riq_ptr]; if (int_info.all & 0xF0000000) /* ha ez nem 0, akkor itt interrupt_info van */ { ack &= ~STAT_PRI; /* don't ack the interrupt, we had some work to do */ channel = PCM_INT_CHANNEL(int_info.all); dev = board->twins[channel]; if (dev == NULL) { printk ("MUNICH_interrupt: got an Rx interrupt info for NULL device " "%s.twins[%d], int_info = 0x%08x\n", board->devname, channel, int_info.all); goto go_for_next_interrupt; } ch = (struct comx_channel *)dev->priv; hw = (struct slicecom_privdata *)ch->HW_privdata; // printk("Rx STAT=0x%08x int_info=0x%08x rx_desc_ptr=%d rx_desc.status=0x%01x\n", // stat, int_info.all, hw->rx_desc_ptr, hw->rx_desc[ hw->rx_desc_ptr ].status ); if (int_info.all & PCM_INT_HI) printk("SliceCOM: %s: Host Initiated interrupt\n", dev->name); if (int_info.all & PCM_INT_IFC) printk("SliceCOM: %s: Idle/Flag Change\n", dev->name); /* TOD: jo ez az Idle/Flag Change valamire? - azonnal latszik belole hogy mikor ad a masik oldal */ /* TOD: ilyen IT most nem is jon, mert ki van maszkolva az interrupt, biztosan kell ez? */ if (int_info.all & PCM_INT_FO) /* Internal buffer (RB) overrun */ ch->stats.rx_over_errors++; /* TOD: Ez azt jelenti hogy a belso RB nem volt hozzaferheto, es ezert kihagyott valamit. De nem csak csomag lehetett, hanem esemeny, stb. is. lasd page 247. Ezzel a 'cat status'-hoz igazodok, de a netdevice.h szerint nem egyertelmu hogy ide ez kellene. Nem lehet hogy rx_missed ? */ /* DE: nem gotozok sehova, elvileg jo igy */ /* kesobb meg visszaterek az FO-ra, ha packet-FO volt. Keresd a "packet-FO"-t. */ if (int_info.all & PCM_INT_FI) /* frame received, but we do not trust the int_info queue */ if (int_info.all & PCM_INT_SF) { /* Short Frame: rovidebb mint a CRC */ /* "rovidebb mint CRC+2byte" vizsgalat a "CRC+2"-nel */ ch->stats.rx_length_errors++; /* TOD: noveljem? ne noveljem? */ goto go_for_next_interrupt; } go_for_next_interrupt: /* One step in the interrupt queue */ board->riq[board->riq_ptr].all = 0; /* megjelolom hogy itt meg nem jart a hw */ board->riq_ptr = (board->riq_ptr + 1) % MUNICH_INTQMAX; } /* Check every Rx ring for incomed packets: */ for (channel = 0; channel < 32; channel++) { dev = board->twins[channel]; if (dev != NULL) { ch = (struct comx_channel *)dev->priv; hw = (struct slicecom_privdata *)ch->HW_privdata; rx_status = hw->rx_desc[hw->rx_desc_ptr].status; if (!(rx_status & 0x80)) /* mar jart itt a hardver */ { ack &= ~STAT_PRI; /* Don't ack, we had some work */ /* Ez most egy kicsit zuros, mert itt mar nem latom az int_infot */ if (rx_status & RX_STATUS_ROF) ch->stats.rx_over_errors++; /* TOD: 'cat status'-hoz igazodok */ if (rx_status & RX_STATUS_RA) /* Abort received or issued on channel */ ch->stats.rx_frame_errors++; /* or HOLD bit in the descriptor */ /* TOD: 'cat status'-hoz igazodok */ if (rx_status & RX_STATUS_LFD) { /* Long Frame (longer then MFL in the MODE1) */ ch->stats.rx_length_errors++; goto go_for_next_frame; } if (rx_status & RX_STATUS_NOB) { /* Not n*8 bits long frame - frame alignment */ ch->stats.rx_frame_errors++; /* ez viszont nem igazodik a 'cat status'-hoz */ goto go_for_next_frame; } if (rx_status & RX_STATUS_CRCO) { /* CRC error */ ch->stats.rx_crc_errors++; goto go_for_next_frame; } if (rx_status & RX_STATUS_SF) { /* Short Frame: rovidebb mint CRC+2byte */ ch->stats.rx_errors++; /* The HW does not set PCI_INT_ERR bit for this one, see page 246 */ ch->stats.rx_length_errors++; goto go_for_next_frame; } if (rx_status != 0) { printk("SliceCOM: %s: unhandled rx_status: 0x%02x\n", dev->name, rx_status); goto go_for_next_frame; } /* frame received without errors: */ length = hw->rx_desc[hw->rx_desc_ptr].bno; ch->stats.rx_packets++; /* Count only 'good' packets */ ch->stats.rx_bytes += length; /* Allocate a larger skb and reserve the heading for efficiency: */ if ((skb = dev_alloc_skb(length + 16)) == NULL) { ch->stats.rx_dropped++; goto go_for_next_frame; } /* Do bookkeeping: */ skb_reserve(skb, 16); skb_put(skb, length); skb->dev = dev; /* Now copy the data into the buffer: */ memcpy(skb->data, &(hw->rx_data[hw->rx_desc_ptr][0]), length); /* DEL: UGLY HACK!!!! */ if (*((int *)skb->data) == 0x02000000 &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -