📄 comx-hw-munich.c
字号:
*(((int *)skb->data) + 1) == 0x3580008f) { printk("%s: swapping hack\n", dev->name); *((int *)skb->data) = 0x3580008f; *(((int *)skb->data) + 1) = 0x02000000; } if (ch->debug_flags & DEBUG_HW_RX) comx_debug_skb(dev, skb, "MUNICH_interrupt receiving"); /* Pass it to the protocol entity: */ ch->LINE_rx(dev, skb); go_for_next_frame: /* DEL: rafutott-e a HOLD bitre -detektalas */ { if( ((rx_desc_t*)phys_to_virt(board->ccb->current_rx_desc[channel]))->hold && ((rx_desc_t*)phys_to_virt(board->ccb->current_rx_desc[channel]))->status != 0xff) hw->rafutott++; /* rafutott: hanyszor volt olyan hogy a current descriptoron HOLD bit volt, es a hw mar befejezte az irast (azaz a hw rafutott a HOLD bitre) */ } // if( jiffies % 2 ) /* DELL: okozzunk egy kis Rx ring slipet :) */ // { /* Step forward with the receive descriptors: */ /* if you change this, change the copy of it below too! Search for: "RxSlip" */ hw->rx_desc[(hw->rx_desc_ptr + RX_DESC_MAX - 1) % RX_DESC_MAX].hold = 1; hw->rx_desc[hw->rx_desc_ptr].status = 0xFF; /* megjelolom hogy itt meg nem jart a hw */ hw->rx_desc[(hw->rx_desc_ptr + RX_DESC_MAX - 2) % RX_DESC_MAX].hold = 0; hw->rx_desc_ptr = (hw->rx_desc_ptr + 1) % RX_DESC_MAX; // } } } } stat &= ~STAT_PRI;// }// if( stat & STAT_PTI ) /* TOD: primko megvalositas: mindig csak egy esemenyt dolgozok fel, */ /* es nem torlom a STAT-ot, ezert ujra visszajon ide a rendszer. Amikor */ /* jon interrupt, de nincs mit feldolgozni, akkor torlom a STAT-ot. */ /* 'needs a rewrite', de elso megoldasnak jo lesz */// { int_info = board->tiq[board->tiq_ptr]; if (int_info.all & 0xF0000000) /* ha ez nem 0, akkor itt interrupt_info van */ { ack &= ~STAT_PTI; /* 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 a Tx interrupt for NULL device " "%s.twins[%d], int_info = 0x%08x\n", board->isx21 ? "pcicom" : "slicecom", channel, int_info.all); goto go_for_next_tx_interrupt; } ch = (struct comx_channel *)dev->priv; hw = (struct slicecom_privdata *)ch->HW_privdata; // printk("Tx STAT=0x%08x int_info=0x%08x tiq_ptr=%d\n", stat, int_info.all, board->tiq_ptr ); if (int_info.all & PCM_INT_FE2) { /* "Tx available" */ /* do nothing */ } else if (int_info.all & PCM_INT_FO) { /* Internal buffer (RB) overrun */ ch->stats.rx_over_errors++; } else { printk("slicecom: %s: unhandled Tx int_info: 0x%08x\n", dev->name, int_info.all); } go_for_next_tx_interrupt: board->tiq[board->tiq_ptr].all = 0; board->tiq_ptr = (board->tiq_ptr + 1) % MUNICH_INTQMAX; } /* Check every Tx ring for incoming packets: */ for (channel = 0; channel < 32; channel++) { dev = board->twins[channel]; if (dev != NULL) { int newbusy; ch = (struct comx_channel *)dev->priv; hw = (struct slicecom_privdata *)ch->HW_privdata; /* We dont trust the "Tx available" info from the TIQ, but check */ /* every ring if there is some free room */ if (ch->init_status && netif_running(dev)) { newbusy = ( TX_DESC_MAX + (& hw->tx_desc[ hw->tx_desc_ptr ]) - (tx_desc_t*)phys_to_virt(board->ccb->current_tx_desc[ hw->channel ]) ) % TX_DESC_MAX; if(newbusy < 0) { printk("slicecom: %s: FATAL: fresly computed busy = %d, HW: 0x%p, SW: 0x%p\n", dev->name, newbusy, phys_to_virt(board->ccb->current_tx_desc[hw->channel]), & hw->tx_desc[hw->tx_desc_ptr]); } /* Fogyott valami a Tx ringbol? */ if (newbusy < hw->busy) { // ack &= ~STAT_PTI; /* Don't ack, we had some work */ hw->busy = newbusy; if (ch->LINE_tx) ch->LINE_tx(dev); /* Report it to protocol driver */ } else if (newbusy > hw->busy) printk("slicecom: %s: newbusy > hw->busy, this should not happen!\n", dev->name); } } } stat &= ~STAT_PTI; int_info = board->piq[board->piq_ptr]; if (int_info.all & 0xF0000000) /* ha ez nem 0, akkor itt interrupt_info van */ { ack &= ~STAT_LBII; /* don't ack the interrupt, we had some work to do */ /* We do not really use (yet) the interrupt info from this queue, */ // printk("slicecom: %s: LBI Interrupt event: %08x\n", board->devname, int_info.all); if (!board->isx21) { slicecom_update_leds(board); slicecom_update_line_counters(board); } goto go_for_next_lbi_interrupt; /* To avoid warning about unused label */ go_for_next_lbi_interrupt: /* One step in the interrupt queue */ board->piq[board->piq_ptr].all = 0; /* megjelolom hogy itt meg nem jart a hw */ board->piq_ptr = (board->piq_ptr + 1) % MUNICH_PIQMAX; } stat &= ~STAT_LBII; writel(ack, MUNICH_VIRT(STAT)); if (stat & STAT_TSPA) { // printk("slicecom: %s: PCM TSP Asynchronous\n", board->devname); writel(STAT_TSPA, MUNICH_VIRT(STAT)); stat &= ~STAT_TSPA; } if (stat & STAT_RSPA) { // printk("slicecom: %s: PCM RSP Asynchronous\n", board->devname); writel(STAT_RSPA, MUNICH_VIRT(STAT)); stat &= ~STAT_RSPA; } if (stat) { printk("MUNICH_interrupt: unhandled interrupt, STAT=0x%08x\n", stat); writel(stat, MUNICH_VIRT(STAT)); /* ha valamit megsem kezeltunk le, azert ack-ot kuldunk neki */ } } board->histogram[work]++; /* We can miss these if we reach the MAX_WORK */ /* Count it to see how often it happens */ if (race_stat & STAT_PRI) board->stat_pri_races_missed++; if (race_stat & STAT_PTI) board->stat_pti_races_missed++; return;}/* * Hardware open routine. * Called by comx (upper) layer when the user wants to bring up the interface * with ifconfig. * Initializes hardware, allocates resources etc. * Returns 0 on OK, or standard error value on error. */static int MUNICH_open(struct net_device *dev){ struct comx_channel *ch = dev->priv; struct slicecom_privdata *hw = ch->HW_privdata; struct proc_dir_entry *procfile = ch->procdir->subdir; munich_board_t *board; munich_ccb_t *ccb; u32 *bar1; u8 *lbi; u32 stat; unsigned long flags, jiffs; int i, channel; u32 timeslots = hw->timeslots; board = hw->boardnum + (ch->hardware == &pcicomhw ? pcicom_boards : slicecom_boards); bar1 = board->bar1; lbi = board->lbi; /* TODO: a timeslotok ellenorzese kell majd ide .. hat, biztos? mar a write_proc-ban is ellenorzom valamennyire. if (!dev->io || !dev->irq) return -ENODEV; */ if (!board->pci) { printk("MUNICH_open: no %s board with boardnum = %d\n", ch->hardware->name, hw->boardnum); return -ENODEV; } spin_lock_irqsave(&mister_lock, flags); /* lock the section to avoid race with multiple opens and make sure that no interrupts get called while this lock is active */ if (board->use_count == 0) /* bring up the board if it was unused */ /* if fails, frees allocated resources and returns. */ /* TOD: is it safe? nem kellene resetelni a kartyat? */ { printk("MUNICH_open: %s: bringing up board\n", board->devname); /* Clean up the board's static struct if messed: */ for (i = 0; i < 32; i++) board->twins[i] = NULL; for (i = 0; i < MAX_WORK; i++) board->histogram[i] = 0; board->lineup = 0; /* Allocate CCB: */ board->ccb = kmalloc(sizeof(munich_ccb_t), GFP_KERNEL); if (board->ccb == NULL) { spin_unlock_irqrestore(&mister_lock, flags); return -ENOMEM; } memset((void *)board->ccb, 0, sizeof(munich_ccb_t)); board->ccb->csa = virt_to_phys(board->ccb); ccb = board->ccb; for (i = 0; i < 32; i++) { ccb->timeslot_spec[i].tti = 1; ccb->timeslot_spec[i].rti = 1; } /* Interrupt queues: */ board->tiq = kmalloc(MUNICH_INTQSIZE, GFP_KERNEL); if (board->tiq == NULL) { spin_unlock_irqrestore(&mister_lock, flags); return -ENOMEM; } memset((void *)board->tiq, 0, MUNICH_INTQSIZE); board->riq = kmalloc(MUNICH_INTQSIZE, GFP_KERNEL); if (board->riq == NULL) { spin_unlock_irqrestore(&mister_lock, flags); return -ENOMEM; } memset((void *)board->riq, 0, MUNICH_INTQSIZE); board->piq = kmalloc(MUNICH_PIQSIZE, GFP_KERNEL); if (board->piq == NULL) { spin_unlock_irqrestore(&mister_lock, flags); return -ENOMEM; } memset((void *)board->piq, 0, MUNICH_PIQSIZE); board->tiq_ptr = 0; board->riq_ptr = 0; board->piq_ptr = 0; /* Request irq: */ board->irq = 0; /* (char*) cast to avoid warning about discarding volatile: */ if (request_irq(board->pci->irq, MUNICH_interrupt, 0, (char *)board->devname, (void *)board)) { printk("MUNICH_open: %s: unable to obtain irq %d\n", board->devname, board->pci->irq); /* TOD: free other resources (a sok malloc feljebb) */ spin_unlock_irqrestore(&mister_lock, flags); return -EAGAIN; } board->irq = board->pci->irq; /* csak akkor legyen != 0, ha tenyleg le van foglalva nekunk */ /* Programming device: */ /* Reset the board like a power-on: */ /* TOD: - It is not a real power-on: if a DMA transaction fails with master abort, the board stays in half-dead state. - It doesn't reset the FALC line driver */ pci_write_config_dword(board->pci, MUNICH_PCI_PCIRES, 0xe0000); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); pci_write_config_dword(board->pci, MUNICH_PCI_PCIRES, 0); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); writel(virt_to_phys(&ccb->csa), MUNICH_VIRT(CCBA)); writel(virt_to_phys( board->tiq ), MUNICH_VIRT(TIQBA)); writel(MUNICH_INTQLEN, MUNICH_VIRT(TIQL)); writel(virt_to_phys( board->riq ), MUNICH_VIRT(RIQBA)); writel(MUNICH_INTQLEN, MUNICH_VIRT(RIQL)); writel(virt_to_phys( board->piq ), MUNICH_VIRT(PIQBA)); writel(MUNICH_PIQLEN, MUNICH_VIRT(PIQL)); /* Put the magic values into the registers: */ writel(MODE1_MAGIC, MUNICH_VIRT(MODE1)); writel(MODE2_MAGIC, MUNICH_VIRT(MODE2)); 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_MAGIC1, MUNICH_VIRT(LCONF)); /* reset the DMSM */ writel(LCONF_MAGIC2, MUNICH_VIRT(LCONF)); /* enable the DMSM */ writel(~0, MUNICH_VIRT(TXPOLL)); writel(board->isx21 ? 0x1400 : 0xa000, MUNICH_VIRT(GPDIR)); if (readl(MUNICH_VIRT(STAT))) writel(readl(MUNICH_VIRT(STAT)), MUNICH_VIRT(STAT)); ccb->action_spec = CCB_ACTIONSPEC_RES | CCB_ACTIONSPEC_IA; writel(CMD_ARPCM, MUNICH_VIRT(CMD)); /* Start the PCM core reset */ set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); stat = 0; /* Wait for the action to complete max. 1 second */ jiffs = jiffies; while (!((stat = readl(MUNICH_VIRT(STAT))) & (STAT_PCMA | STAT_PCMF)) && time_before(jiffies, jiffs + HZ)) { set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); } if (stat & STAT_PCMF) { printk(KERN_ERR "MUNICH_open: %s: Initial ARPCM failed. STAT=0x%08x\n", board->devname, stat); writel(readl(MUNICH_VIRT(STAT)) & STAT_PCMF, MUNICH_VIRT(STAT)); free_irq(board->irq, (void *)board); /* TOD: free other resources too *//* maybe shut down hw? */ board->irq = 0; spin_unlock_irqrestore(&mister_lock, flags); return -EAGAIN; } else if (!(stat & STAT_PCMA)) { printk(KERN_ERR "MUNICH_open: %s: Initial ARPCM timeout. STAT=0x%08x\n", board->devname, stat); free_irq(board->irq, (void *)board); /* TOD: free other resources too *//* maybe shut off the hw? */ board->irq = 0; spin_unlock_irqrestore(&mister_lock, flags); return -EIO; } writel(readl(MUNICH_VIRT(STAT)) & STAT_PCMA, MUNICH_VIRT(STAT)); /* Acknowledge */ if (board->isx21) writel(0, MUNICH_VIRT(GPDATA)); printk("MUNICH_open: %s: succesful HW-open took %ld jiffies\n", board->devname, jiffies - jiffs); /* Set up the FALC hanging on the Local Bus: */ if (!board->isx21) { writeb(0x0e, lbi + FMR1); writeb(0, lbi + LIM0); writeb(0xb0, lbi + LIM1); /* TODO: input threshold */ writeb(0xf7, lbi + XPM0); writeb(0x02, lbi + XPM1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -