⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 comx-hw-munich.c

📁 该文件是rt_linux
💻 C
📖 第 1 页 / 共 5 页
字号:
			*(((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 + -