📄 comx-hw-munich.c
字号:
writeb(0x00, lbi + XPM2); writeb(0xf0, lbi + FMR0); writeb(0x80, lbi + PCD); writeb(0x80, lbi + PCR); writeb(0x00, lbi + LIM2); writeb(0x07, lbi + XC0); writeb(0x3d, lbi + XC1); writeb(0x05, lbi + RC0); writeb(0x00, lbi + RC1); writeb(0x83, lbi + FMR2); writeb(0x9f, lbi + XSW); writeb(0x0f, lbi + XSP); writeb(0x00, lbi + TSWM); writeb(0xe0, lbi + MODE); writeb(0xff, lbi + IDLE); /* Idle Code to send in unused timeslots */ writeb(0x83, lbi + IPC); /* interrupt query line mode: Push/pull output, active high */ writeb(0xbf, lbi + IMR3); /* send an interrupt every second */ slicecom_set_framing(hw->boardnum, board->framing); slicecom_set_linecode(hw->boardnum, board->linecode); slicecom_set_clock_source(hw->boardnum, board->clock_source); slicecom_set_loopback(hw->boardnum, board->loopback); memset((void *)board->intervals, 0, sizeof(board->intervals)); board->current_interval = 0; board->elapsed_seconds = 0; board->ses_seconds = 0; board->is_unavailable = 0; board->no_ses_seconds = 0; board->deg_elapsed_seconds = 0; board->deg_cumulated_errors = 0; } /* Enable the interrupts last */ /* These interrupts will be enabled. We do not need the others. */ writel(readl(MUNICH_VIRT(IMASK)) & ~(STAT_PTI | STAT_PRI | STAT_LBII | STAT_TSPA | STAT_RSPA), MUNICH_VIRT(IMASK)); } spin_unlock_irqrestore(&mister_lock, flags); dev->irq = board->irq; /* hogy szep legyen az ifconfig outputja */ ccb = board->ccb; /* TODO: ez igy csunya egy kicsit hogy benn is meg kinn is beletoltom :( */ spin_lock_irqsave(&mister_lock, flags); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); /* Check if the selected timeslots aren't used already */ for (i = 0; i < 32; i++) if (((1 << i) & timeslots) && !ccb->timeslot_spec[i].tti) { printk("MUNICH_open: %s: timeslot %d already used by %s\n", dev->name, i, board->twins[ccb->timeslot_spec[i].txchannel]->name); spin_unlock_irqrestore(&mister_lock, flags); return -EBUSY; /* TODO: lehet hogy valami mas errno kellene? */ } /* find a free channel: */ /* TODO: ugly, rewrite it */ for (channel = 0; channel <= 32; channel++) { if (channel == 32) { /* not found a free one */ printk ("MUNICH_open: %s: FATAL: can not find a free channel - this should not happen!\n", dev->name); spin_unlock_irqrestore(&mister_lock, flags); return -ENODEV; } if (board->twins[channel] == NULL) break; /* found the first free one */ } board->lastcheck = jiffies; /* avoid checking uninitialized hardware channel */ /* Open the channel. If fails, calls MUNICH_close() to properly free resources and stop the HW */ hw->channel = channel; board->twins[channel] = dev; board->use_count++; /* meg nem nyitottuk meg a csatornat, de a twins-ben mar elfoglaltunk egyet, es ha a _close-t akarjuk hivni, akkor ez kell. */ for (i = 0; i < 32; i++) if ((1 << i) & timeslots) { ccb->timeslot_spec[i].tti = 0; ccb->timeslot_spec[i].txchannel = channel; ccb->timeslot_spec[i].txfillmask = ~0; ccb->timeslot_spec[i].rti = 0; ccb->timeslot_spec[i].rxchannel = channel; ccb->timeslot_spec[i].rxfillmask = ~0; } if (!board->isx21) rework_idle_channels(dev); memset((void *)&(hw->tx_desc), 0, TX_DESC_MAX * sizeof(tx_desc_t)); memset((void *)&(hw->rx_desc), 0, RX_DESC_MAX * sizeof(rx_desc_t)); for (i = 0; i < TX_DESC_MAX; i++) { hw->tx_desc[i].fe = 1; hw->tx_desc[i].fnum = 2; hw->tx_desc[i].data = virt_to_phys( & (hw->tx_data[i][0]) ); hw->tx_desc[i].next = virt_to_phys( & (hw->tx_desc[ (i+1) % TX_DESC_MAX ]) ); } hw->tx_desc_ptr = 0; /* we will send an initial packet so it is correct: "oda irtunk utoljara" */ hw->busy = 0; hw->tx_desc[hw->tx_desc_ptr].hold = 1; hw->tx_desc[hw->tx_desc_ptr].no = 1; /* TOD: inkabb csak 0 hosszut kuldjunk ki az initkor? */ for (i = 0; i < RX_DESC_MAX; i++) { hw->rx_desc[i].no = RXBUFFER_SIZE; hw->rx_desc[i].data = virt_to_phys(&(hw->rx_data[i][0])); hw->rx_desc[i].next = virt_to_phys(&(hw->rx_desc[(i+1) % RX_DESC_MAX])); hw->rx_desc[i].status = 0xFF; } hw->rx_desc_ptr = 0; hw->rx_desc[(hw->rx_desc_ptr + RX_DESC_MAX - 2) % RX_DESC_MAX].hold = 1; memset((void *)&ccb->channel_spec[channel], 0, sizeof(channel_spec_t)); ccb->channel_spec[channel].ti = 0; /* Transmit off */ ccb->channel_spec[channel].to = 1; ccb->channel_spec[channel].ta = 0; ccb->channel_spec[channel].th = 1; /* Transmit hold */ ccb->channel_spec[channel].ri = 0; /* Receive off */ ccb->channel_spec[channel].ro = 1; ccb->channel_spec[channel].ra = 0; ccb->channel_spec[channel].mode = 3; /* HDLC */ ccb->action_spec = CCB_ACTIONSPEC_IN | (channel << 8); writel(CMD_ARPCM, MUNICH_VIRT(CMD)); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); spin_unlock_irqrestore(&mister_lock, flags); stat = 0; 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: %s channel %d off failed\n", dev->name, board->devname, channel); writel(readl(MUNICH_VIRT(STAT)) & STAT_PCMF, MUNICH_VIRT(STAT)); MUNICH_close(dev); return -EAGAIN; } else if (!(stat & STAT_PCMA)) { printk(KERN_ERR "MUNICH_open: %s: %s channel %d off timeout\n", dev->name, board->devname, channel); MUNICH_close(dev); return -EIO; } writel(readl(MUNICH_VIRT(STAT)) & STAT_PCMA, MUNICH_VIRT(STAT)); // printk("MUNICH_open: %s: succesful channel off took %ld jiffies\n", board->devname, jiffies-jiffs); spin_lock_irqsave(&mister_lock, flags); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); ccb->channel_spec[channel].ifc = 1; /* 1 .. 'Idle/Flag change' interrupt letiltva */ ccb->channel_spec[channel].fit = 1; ccb->channel_spec[channel].nitbs = 1; ccb->channel_spec[channel].itbs = 2; /* TODOO: lehet hogy jo lenne igy, de utana kellene nezni hogy nem okoz-e fragmentaciot */ // ccb->channel_spec[channel].itbs = 2 * number_of_timeslots; // printk("open: %s: number_of_timeslots: %d\n", dev->name, number_of_timeslots); ccb->channel_spec[channel].mode = 3; /* HDLC */ ccb->channel_spec[channel].ftda = virt_to_phys(&(hw->tx_desc)); ccb->channel_spec[channel].frda = virt_to_phys(&(hw->rx_desc[0])); ccb->channel_spec[channel].ti = 1; /* Transmit init */ ccb->channel_spec[channel].to = 0; ccb->channel_spec[channel].ta = 1; ccb->channel_spec[channel].th = 0; ccb->channel_spec[channel].ri = 1; /* Receive init */ ccb->channel_spec[channel].ro = 0; ccb->channel_spec[channel].ra = 1; ccb->action_spec = CCB_ACTIONSPEC_ICO | (channel << 8); writel(CMD_ARPCM, MUNICH_VIRT(CMD)); /* Start the channel init */ set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); spin_unlock_irqrestore(&mister_lock, flags); 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: channel open ARPCM failed\n", board->devname); writel(readl(MUNICH_VIRT(STAT)) & STAT_PCMF, MUNICH_VIRT(STAT)); MUNICH_close(dev); return -EAGAIN; } else if (!(stat & STAT_PCMA)) { printk(KERN_ERR "MUNICH_open: %s: channel open ARPCM timeout\n", board->devname); MUNICH_close(dev); return -EIO; } writel(readl(MUNICH_VIRT(STAT)) & STAT_PCMA, MUNICH_VIRT(STAT)); // printk("MUNICH_open: %s: succesful channel open took %ld jiffies\n", board->devname, jiffies-jiffs); spin_lock_irqsave(&mister_lock, flags); ccb->channel_spec[channel].nitbs = 0; /* once ITBS defined, these must be 0 */ ccb->channel_spec[channel].itbs = 0; if (board->isx21) { board->modemline_timer.data = (unsigned long)board; board->modemline_timer.function = pcicom_modemline; board->modemline_timer.expires = jiffies + HZ; add_timer((struct timer_list *)&board->modemline_timer); } /* It is done. Declare that we're open: */ hw->busy = 0; /* It may be 1 if the frame at Tx init already ended, but it is not */ /* a real problem: we compute hw->busy on every interrupt */ hw->rafutott = 0; ch->init_status |= HW_OPEN; /* Initialize line state: */ if (board->lineup) ch->line_status |= LINE_UP; else ch->line_status &= ~LINE_UP; /* Remove w attribute from /proc files associated to hw parameters: no write when the device is open */ for (; procfile; procfile = procfile->next) if (strcmp(procfile->name, FILENAME_BOARDNUM) == 0 || strcmp(procfile->name, FILENAME_TIMESLOTS) == 0) procfile->mode = S_IFREG | 0444; spin_unlock_irqrestore(&mister_lock, flags); return 0;}/* * Hardware close routine. * Called by comx (upper) layer when the user wants to bring down the interface * with ifconfig. * We also call it from MUNICH_open, if the open fails. * Brings down hardware, frees resources, stops receiver * Returns 0 on OK, or standard error value on error. */static int MUNICH_close(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; u32 timeslots = hw->timeslots; int stat, i, channel = hw->channel; unsigned long jiffs; board = hw->boardnum + (ch->hardware == &pcicomhw ? pcicom_boards : slicecom_boards); ccb = board->ccb; bar1 = board->bar1; if (board->isx21) del_timer((struct timer_list *)&board->modemline_timer); spin_lock_irqsave(&mister_lock, flags); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); /* Disable receiver for the channel: */ for (i = 0; i < 32; i++) if ((1 << i) & timeslots) { ccb->timeslot_spec[i].tti = 1; ccb->timeslot_spec[i].txfillmask = 0; /* just to be double-sure :) */ ccb->timeslot_spec[i].rti = 1; ccb->timeslot_spec[i].rxfillmask = 0; } if (!board->isx21) rework_idle_channels(dev); ccb->channel_spec[channel].ti = 0; /* Receive off, Transmit off */ ccb->channel_spec[channel].to = 1; ccb->channel_spec[channel].ta = 0; ccb->channel_spec[channel].th = 1; ccb->channel_spec[channel].ri = 0; ccb->channel_spec[channel].ro = 1; ccb->channel_spec[channel].ra = 0; board->twins[channel] = NULL; ccb->action_spec = CCB_ACTIONSPEC_IN | (channel << 8); writel(CMD_ARPCM, MUNICH_VIRT(CMD)); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); spin_unlock_irqrestore(&mister_lock, flags); stat = 0; 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_close: %s: FATAL: channel off ARPCM failed, not closing!\n", dev->name); writel(readl(MUNICH_VIRT(STAT)) & STAT_PCMF, MUNICH_VIRT(STAT)); /* If we return success, the privdata (and the descriptor list) will be freed */ return -EIO; } else if (!(stat & STAT_PCMA)) printk(KERN_ERR "MUNICH_close: %s: channel off ARPCM timeout\n", board->devname); writel(readl(MUNICH_VIRT(STAT)) & STAT_PCMA, MUNICH_VIRT(STAT)); // printk("MUNICH_close: %s: channel off took %ld jiffies\n", board->devname, jiffies-jiffs); spin_lock_irqsave(&mister_lock, flags); if (board->use_count) board->use_count--; if (!board->use_count) /* we were the last user of the board */ { printk("MUNICH_close: bringing down board %s\n", board->devname); /* program down the board: */ writel(0x0000FF7F, MUNICH_VIRT(IMASK)); /* do not send any interrupts */ writel(0, MUNICH_VIRT(CMD)); /* stop the timer if someone started it */ writel(~0U, MUNICH_VIRT(STAT)); /* if an interrupt came between the cli()-sti(), quiet it */ if (ch->hardware == &pcicomhw) writel(0x1400, MUNICH_VIRT(GPDATA)); /* Put the board into 'reset' state: */ pci_write_config_dword(board->pci, MUNICH_PCI_PCIRES, 0xe0000); /* Free irq and other resources: */ if (board->irq) free_irq(board->irq, (void *)board); /* Ha nem inicializalta magat, akkor meg nincs irq */ board->irq = 0; /* Free CCB and the interrupt queues */ if (board->ccb) kfree((void *)board->ccb); if (board->tiq) kfree((void *)board->tiq); if (board->riq) kfree((void *)board->riq); if (board->piq) kfree((void *)board->piq); board->ccb = NULL; board->tiq = board->riq = board->piq = NULL; } /* Enable setting of hw parameters */ for (; procfile; procfile = procfile->next) if (strcmp(procfile->name, FILENAME_BOARDNUM) == 0 || strcmp(procfile->name, FILENAME_TIMESLOTS)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -