static int LOCOMX_open(struct net_device *dev) { struct comx_channel *ch = netdev_priv(dev); struct locomx_data *hw = ch->HW_privdata; struct proc_dir_entry *procfile = ch->procdir->subdir; unsigned long flags; int ret; if (!dev->base_addr || !dev->irq) { return -ENODEV; } if (!request_region(dev->base_addr, hw->io_extent, dev->name)) { return -EAGAIN; } hw->board.chanA.ctrlio=dev->base_addr + 5; hw->board.chanA.dataio=dev->base_addr + 7; hw->board.irq=dev->irq; hw->board.chanA.netdevice=dev; hw->board.chanA.dev=&hw->board; hw->board.name=dev->name; hw->board.chanA.txdma=TX_DMA; hw->board.chanA.rxdma=RX_DMA; hw->board.chanA.irqs=&z8530_nop; hw->board.chanB.irqs=&z8530_nop; if(request_irq(dev->irq, z8530_interrupt, SA_INTERRUPT, dev->name, &hw->board)) { printk(KERN_ERR "%s: unable to obtain irq %d\n", dev->name, dev->irq); ret=-EAGAIN; goto irq_fail; } if(request_dma(TX_DMA,"LoCOMX (TX)")) { printk(KERN_ERR "%s: unable to obtain TX DMA (DMA channel %d)\n", dev->name, TX_DMA); ret=-EAGAIN; goto dma1_fail; } if(request_dma(RX_DMA,"LoCOMX (RX)")) { printk(KERN_ERR "%s: unable to obtain RX DMA (DMA channel %d)\n", dev->name, RX_DMA); ret=-EAGAIN; goto dma2_fail; } save_flags(flags); cli(); if(z8530_init(&hw->board)!=0) { printk(KERN_ERR "%s: Z8530 device not found.\n",dev->name); ret=-ENODEV; goto z8530_fail; } hw->board.chanA.dcdcheck=CTS; z8530_channel_load(&hw->board.chanA, z8530_hdlc_kilostream_85230); z8530_channel_load(&hw->board.chanA, z8530_locomx); z8530_channel_load(&hw->board.chanB, z8530_dead_port); z8530_describe(&hw->board, "I/O", dev->base_addr); if((ret=z8530_sync_dma_open(dev, &hw->board.chanA))!=0) { goto z8530_fail; } restore_flags(flags); hw->board.active=1; hw->board.chanA.rx_function=locomx_rx; ch->init_status |= HW_OPEN; if (hw->board.chanA.status & DCD) { ch->line_status |= LINE_UP; } else { ch->line_status &= ~LINE_UP; } comx_status(dev, ch->line_status); init_timer(&hw->status_timer); hw->status_timer.function=locomx_status_timerfun; hw->status_timer.data=(unsigned long)dev; hw->status_timer.expires=jiffies + ch->lineup_delay * HZ; add_timer(&hw->status_timer); for (; procfile ; procfile = procfile->next) { if (strcmp(procfile->name, FILENAME_IO) == 0 || strcmp(procfile->name, FILENAME_IRQ) == 0) { procfile->mode = S_IFREG | 0444; } } return 0; z8530_fail: restore_flags(flags); free_dma(RX_DMA); dma2_fail: free_dma(TX_DMA); dma1_fail: free_irq(dev->irq, &hw->board); irq_fail: release_region(dev->base_addr, hw->io_extent); return ret; }
static void nm256_startRecording (struct nm256_info *card, char *buffer, u32 amt) { u32 endpos; int enableEngine = 0; u32 ringsize = card->recordBufferSize; unsigned long flags; if (amt > (ringsize / 2)) { /* * Of course this won't actually work right, because the * caller is going to assume we will give what we got asked * for. */ printk (KERN_ERR "NM256: Read request too large: %d\n", amt); amt = ringsize / 2; } if (amt < 8) { printk (KERN_ERR "NM256: Read request too small; %d\n", amt); return; } save_flags (flags); cli (); /* * If we're not currently recording, set up the start and end registers * for the recording engine. */ if (! card->recording) { card->recording = 1; if (nm256_grabInterrupt (card) == 0) { card->curRecPos = 0; nm256_setInfo (card->dev_for_record, card); nm256_writePort32 (card, 2, NM_RBUFFER_START, card->abuf2); nm256_writePort32 (card, 2, NM_RBUFFER_END, card->abuf2 + ringsize); nm256_writePort32 (card, 2, NM_RBUFFER_CURRP, card->abuf2 + card->curRecPos); enableEngine = 1; } else { /* Not sure what else to do here. */ restore_flags (flags); return; } } /* * If we happen to go past the end of the buffer a bit (due to a * delayed interrupt) it's OK. So might as well set the watermark * right at the end of the data we want. */ endpos = card->abuf2 + ((card->curRecPos + amt) % ringsize); card->recBuf = buffer; card->requestedRecAmt = amt; nm256_writePort32 (card, 2, NM_RBUFFER_WMARK, endpos); /* Enable recording engine and interrupts. */ if (enableEngine) nm256_writePort8 (card, 2, NM_RECORD_ENABLE_REG, NM_RECORD_ENABLE_FLAG | NM_RECORD_FREERUN); restore_flags (flags); }
static struct sk_buff *hfc_empty_fifo(struct BCState *bcs, int count) { u_char *ptr; struct sk_buff *skb; struct IsdnCardState *cs = bcs->cs; int idx; int chksum; long flags; u_char stat, cip; char tmp[64]; if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) debugl1(cs, "hfc_empty_fifo"); idx = 0; save_flags(flags); if (count > HSCX_BUFMAX + 3) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "hfc_empty_fifo: incoming packet too large"); cip = HFCB_FIFO | HFCB_FIFO_OUT | HFCB_REC | HFCB_CHANNEL(bcs->channel); while (idx++ < count) { cli(); WaitNoBusy(cs); ReadReg(cs, HFCD_DATA_NODEB, cip); sti(); } skb = NULL; } else if (count < 4) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "hfc_empty_fifo: incoming packet too small"); cip = HFCB_FIFO | HFCB_FIFO_OUT | HFCB_REC | HFCB_CHANNEL(bcs->channel); cli(); while ((idx++ < count) && WaitNoBusy(cs)) ReadReg(cs, HFCD_DATA_NODEB, cip); skb = NULL; } else if (!(skb = dev_alloc_skb(count - 3))) printk(KERN_WARNING "HFC: receive out of memory\n"); else { ptr = skb_put(skb, count - 3); idx = 0; cip = HFCB_FIFO | HFCB_FIFO_OUT | HFCB_REC | HFCB_CHANNEL(bcs->channel); cli(); while (idx < (count - 3)) { cli(); if (!WaitNoBusy(cs)) break; *ptr = ReadReg(cs, HFCD_DATA_NODEB, cip); sti(); ptr++; idx++; } if (idx != count - 3) { sti(); debugl1(cs, "RFIFO BUSY error"); printk(KERN_WARNING "HFC FIFO channel %d BUSY Error\n", bcs->channel); dev_kfree_skb(skb); skb = NULL; } else { cli(); WaitNoBusy(cs); chksum = (ReadReg(cs, HFCD_DATA, cip) << 8); WaitNoBusy(cs); chksum += ReadReg(cs, HFCD_DATA, cip); WaitNoBusy(cs); stat = ReadReg(cs, HFCD_DATA, cip); sti(); if (cs->debug & L1_DEB_HSCX) { sprintf(tmp, "hfc_empty_fifo %d chksum %x stat %x", bcs->channel, chksum, stat); debugl1(cs, tmp); } if (stat) { debugl1(cs, "FIFO CRC error"); dev_kfree_skb(skb); skb = NULL; } } } sti(); WaitForBusy(cs); cli(); WaitNoBusy(cs); stat = ReadReg(cs, HFCD_DATA, HFCB_FIFO | HFCB_F2_INC | HFCB_REC | HFCB_CHANNEL(bcs->channel)); sti(); WaitForBusy(cs); restore_flags(flags); return (skb); }
void icc_interrupt(struct IsdnCardState *cs, u_char val) { u_char exval, v1; struct sk_buff *skb; unsigned int count; long flags; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ICC interrupt %x", val); if (val & 0x80) { /* RME */ exval = cs->readisac(cs, ICC_RSTA); if ((exval & 0x70) != 0x20) { if (exval & 0x40) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "ICC RDO"); #ifdef ERROR_STATISTIC cs->err_rx++; #endif } if (!(exval & 0x20)) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "ICC CRC error"); #ifdef ERROR_STATISTIC cs->err_crc++; #endif } cs->writeisac(cs, ICC_CMDR, 0x80); } else { count = cs->readisac(cs, ICC_RBCL) & 0x1f; if (count == 0) count = 32; icc_empty_fifo(cs, count); save_flags(flags); cli(); if ((count = cs->rcvidx) > 0) { cs->rcvidx = 0; if (!(skb = alloc_skb(count, GFP_ATOMIC))) printk(KERN_WARNING "HiSax: D receive out of memory\n"); else { memcpy(skb_put(skb, count), cs->rcvbuf, count); skb_queue_tail(&cs->rq, skb); } } restore_flags(flags); } cs->rcvidx = 0; icc_sched_event(cs, D_RCVBUFREADY); } if (val & 0x40) { /* RPF */ icc_empty_fifo(cs, 32); } if (val & 0x20) { /* RSC */ /* never */ if (cs->debug & L1_DEB_WARN) debugl1(cs, "ICC RSC interrupt"); } if (val & 0x10) { /* XPR */ if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) del_timer(&cs->dbusytimer); if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) icc_sched_event(cs, D_CLEARBUSY); if (cs->tx_skb) { if (cs->tx_skb->len) { icc_fill_fifo(cs); goto afterXPR; } else { dev_kfree_skb_irq(cs->tx_skb); cs->tx_cnt = 0; cs->tx_skb = NULL; } } if ((cs->tx_skb = skb_dequeue(&cs->sq))) { cs->tx_cnt = 0; icc_fill_fifo(cs); } else icc_sched_event(cs, D_XMTBUFREADY); } afterXPR: if (val & 0x04) { /* CISQ */ exval = cs->readisac(cs, ICC_CIR0); if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ICC CIR0 %02X", exval ); if (exval & 2) { cs->dc.icc.ph_state = (exval >> 2) & 0xf; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ph_state change %x", cs->dc.icc.ph_state); icc_sched_event(cs, D_L1STATECHANGE); }
__LDDK_WRITE_TYPE can_write( __LDDK_WRITE_PARAM ) { unsigned int minor = __LDDK_MINOR; msg_fifo_t *TxFifo = &Tx_Buf[minor]; canmsg_t *addr; canmsg_t tx; unsigned long flags; int written = 0; DBGin("can_write"); #ifdef DEBUG_COUNTER Cnt1[minor] = Cnt1[minor] + 1; #endif /* DEBUG_COUNTER */ /* DEBUG_TTY(1, "write: %d", count); */ DBGprint(DBG_DATA,(" -- write %d msg\n", count)); /* printk("w[%d/%d]", minor, TxFifo->active); */ addr = (canmsg_t *)buffer; if(verify_area(VERIFY_READ, (canmsg_t *)addr, count * sizeof(canmsg_t))) { DBGout();return -EINVAL; } while( written < count ) { /* enter critical section */ save_flags(flags);cli(); /* there are data to write to the network */ if(TxFifo->free[TxFifo->head] == BUF_FULL) { /* DEBUG_TTY(1, "ret buffer full"); */ /* there is already one message at this place */; DBGout(); /* return -ENOSPC; */ return written; } if( TxFifo->active ) { /* more than one data and actual data in queue */ __lddk_copy_from_user( /* copy one message to FIFO */ (canmsg_t *) &(TxFifo->data[TxFifo->head]), (canmsg_t *) &addr[written], sizeof(canmsg_t) ); /* DEBUG_TTY(1, " fifo active: id %d/%x; head %d/tail %d", */ /* TxFifo->data[TxFifo->head].id, */ /* TxFifo->data[TxFifo->head].id, */ /* TxFifo->head, */ /* TxFifo->tail); */ TxFifo->free[TxFifo->head] = BUF_FULL; /* now this entry is FULL */ TxFifo->head = ++(TxFifo->head) % MAX_BUFSIZE; } else { __lddk_copy_from_user( (canmsg_t *) &tx, (canmsg_t *) &addr[written], sizeof(canmsg_t) ); /* DEBUG_TTY(1, " fifo in-active: id %d/%x; head %d/tail %d", */ /* tx.id, tx.id, */ /* TxFifo->head, */ /* TxFifo->tail ); */ /* f - fast -- use interrupts */ if( count >= 1 ) { /* !!! CHIP abh. !!! */ TxFifo->active = 1; } CAN_SendMessage( minor, &tx); /* Send, no wait */ } written++; /* leave critical section */ restore_flags(flags); } /* printk("W[%d/%d]", minor, TxFifo->active); */ DBGout(); return written; }
int isdn_divert_icall(isdn_ctrl *ic) { int retval = 0; int flags; struct call_struc *cs = NULL; struct deflect_struc *dv; char *p,*p1; u_char accept; /* first check the internal deflection table */ for (dv = table_head; dv ; dv = dv->next ) { /* scan table */ if (((dv->rule.callopt == 1) && (ic->command == ISDN_STAT_ICALLW)) || ((dv->rule.callopt == 2) && (ic->command == ISDN_STAT_ICALL))) continue; /* call option check */ if (!(dv->rule.drvid & (1L << ic->driver))) continue; /* driver not matching */ if ((dv->rule.si1) && (dv->rule.si1 != ic->parm.setup.si1)) continue; /* si1 not matching */ if ((dv->rule.si2) && (dv->rule.si2 != ic->parm.setup.si2)) continue; /* si2 not matching */ p = dv->rule.my_msn; p1 = ic->parm.setup.eazmsn; accept = 0; while (*p) { /* complete compare */ if (*p == '-') { accept = 1; /* call accepted */ break; } if (*p++ != *p1++) break; /* not accepted */ if ((!*p) && (!*p1)) accept = 1; } /* complete compare */ if (!accept) continue; /* not accepted */ if ((strcmp(dv->rule.caller,"0")) || (ic->parm.setup.phone[0])) { p = dv->rule.caller; p1 = ic->parm.setup.phone; accept = 0; while (*p) { /* complete compare */ if (*p == '-') { accept = 1; /* call accepted */ break; } if (*p++ != *p1++) break; /* not accepted */ if ((!*p) && (!*p1)) accept = 1; } /* complete compare */ if (!accept) continue; /* not accepted */ } switch (dv->rule.action) { case DEFLECT_IGNORE: return(0); break; case DEFLECT_ALERT: case DEFLECT_PROCEED: case DEFLECT_REPORT: case DEFLECT_REJECT: if (dv->rule.action == DEFLECT_PROCEED) if ((!if_used) || ((!extern_wait_max) && (!dv->rule.waittime))) return(0); /* no external deflection needed */ if (!(cs = (struct call_struc *) kmalloc(sizeof(struct call_struc), GFP_ATOMIC))) return(0); /* no memory */ init_timer(&cs->timer); cs->info[0] = '\0'; cs->timer.function = deflect_timer_expire; cs->timer.data = (ulong) cs; /* pointer to own structure */ cs->ics = *ic; /* copy incoming data */ if (!cs->ics.parm.setup.phone[0]) strcpy(cs->ics.parm.setup.phone,"0"); if (!cs->ics.parm.setup.eazmsn[0]) strcpy(cs->ics.parm.setup.eazmsn,"0"); cs->ics.parm.setup.screen = dv->rule.screen; if (dv->rule.waittime) cs->timer.expires = jiffies + (HZ * dv->rule.waittime); else if (dv->rule.action == DEFLECT_PROCEED) cs->timer.expires = jiffies + (HZ * extern_wait_max); else cs->timer.expires = 0; cs->akt_state = dv->rule.action; save_flags(flags); cli(); cs->divert_id = next_id++; /* new sequence number */ restore_flags(flags); cs->prev = NULL; if (cs->akt_state == DEFLECT_ALERT) { strcpy(cs->deflect_dest,dv->rule.to_nr); if (!cs->timer.expires) { strcpy(ic->parm.setup.eazmsn,"Testtext direct"); ic->parm.setup.screen = dv->rule.screen; strcpy(ic->parm.setup.phone,dv->rule.to_nr); cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); retval = 5; } else retval = 1; /* alerting */ } else { cs->deflect_dest[0] = '\0'; retval = 4; /* only proceed */ } sprintf(cs->info,"%d 0x%lx %s %s %s %s 0x%x 0x%x %d %d %s\n", cs->akt_state, cs->divert_id, divert_if.drv_to_name(cs->ics.driver), (ic->command == ISDN_STAT_ICALLW) ? "1":"0", cs->ics.parm.setup.phone, cs->ics.parm.setup.eazmsn, cs->ics.parm.setup.si1, cs->ics.parm.setup.si2, cs->ics.parm.setup.screen, dv->rule.waittime, cs->deflect_dest); if ((dv->rule.action == DEFLECT_REPORT) || (dv->rule.action == DEFLECT_REJECT)) { put_info_buffer(cs->info); kfree(cs); /* remove */ return((dv->rule.action == DEFLECT_REPORT) ? 0:2); /* nothing to do */ } break; default: return(0); /* ignore call */ break; } /* switch action */ break; } /* scan_table */ if (cs) { cs->prev = NULL; save_flags(flags); cli(); cs->next = divert_head; divert_head = cs; if (cs->timer.expires) add_timer(&cs->timer); restore_flags(flags); put_info_buffer(cs->info); return(retval); } else return(0); } /* isdn_divert_icall */
/* * Poll a virtual cards message queue. * If there are new status-replies from the card, copy them to * ringbuffer for reading on /dev/isdnctrl and call * isdnloop_parse_status() for processing them. Watch for special * Firmware bootmessage and parse it, to get the D-Channel protocol. * If there are B-Channels open, initiate a timer-callback to * isdnloop_pollbchan(). * This routine is called periodically via timer interrupt. * * Parameter: * data = pointer to card struct */ static void isdnloop_polldchan(unsigned long data) { isdnloop_card *card = (isdnloop_card *) data; struct sk_buff *skb; int avail; int left; u_char c; int ch; unsigned long flags; u_char *p; isdn_ctrl cmd; if ((skb = skb_dequeue(&card->dqueue))) avail = skb->len; else avail = 0; for (left = avail; left > 0; left--) { c = *skb->data; skb_pull(skb, 1); isdnloop_putmsg(card, c); card->imsg[card->iptr] = c; if (card->iptr < 59) card->iptr++; if (!skb->len) { avail++; isdnloop_putmsg(card, '\n'); card->imsg[card->iptr] = 0; card->iptr = 0; if (card->imsg[0] == '0' && card->imsg[1] >= '0' && card->imsg[1] <= '2' && card->imsg[2] == ';') { ch = (card->imsg[1] - '0') - 1; p = &card->imsg[3]; isdnloop_parse_status(p, ch, card); } else { p = card->imsg; if (!strncmp(p, "DRV1.", 5)) { printk(KERN_INFO "isdnloop: (%s) %s\n", CID, p); if (!strncmp(p + 7, "TC", 2)) { card->ptype = ISDN_PTYPE_1TR6; card->interface.features |= ISDN_FEATURE_P_1TR6; printk(KERN_INFO "isdnloop: (%s) 1TR6-Protocol loaded and running\n", CID); } if (!strncmp(p + 7, "EC", 2)) { card->ptype = ISDN_PTYPE_EURO; card->interface.features |= ISDN_FEATURE_P_EURO; printk(KERN_INFO "isdnloop: (%s) Euro-Protocol loaded and running\n", CID); } continue; } } } } if (avail) { cmd.command = ISDN_STAT_STAVAIL; cmd.driver = card->myid; cmd.arg = avail; card->interface.statcallb(&cmd); } if (card->flags & (ISDNLOOP_FLAGS_B1ACTIVE | ISDNLOOP_FLAGS_B2ACTIVE)) if (!(card->flags & ISDNLOOP_FLAGS_RBTIMER)) { /* schedule b-channel polling */ card->flags |= ISDNLOOP_FLAGS_RBTIMER; save_flags(flags); cli(); del_timer(&card->rb_timer); card->rb_timer.function = isdnloop_pollbchan; card->rb_timer.data = (unsigned long) card; card->rb_timer.expires = jiffies + ISDNLOOP_TIMER_BCREAD; add_timer(&card->rb_timer); restore_flags(flags); } /* schedule again */ save_flags(flags); cli(); card->st_timer.expires = jiffies + ISDNLOOP_TIMER_DCREAD; add_timer(&card->st_timer); restore_flags(flags); }
static int ip_msqhst_procinfo(char *buffer, char **start, off_t offset, int length, int unused) { off_t pos=0, begin; struct ip_masq *ms; unsigned long flags; char temp[129]; int idx = 0; int len=0; if (offset < 128) { #ifdef CONFIG_IP_MASQUERADE_ICMP sprintf(temp, "Prc FromIP FPrt ToIP TPrt Masq Init-seq Delta PDelta Expires (free=%d,%d,%d)", ip_masq_free_ports[0], ip_masq_free_ports[1], ip_masq_free_ports[2]); #else /* !defined(CONFIG_IP_MASQUERADE_ICMP) */ sprintf(temp, "Prc FromIP FPrt ToIP TPrt Masq Init-seq Delta PDelta Expires (free=%d,%d)", ip_masq_free_ports[0], ip_masq_free_ports[1]); #endif /* CONFIG_IP_MASQUERADE_ICMP */ len = sprintf(buffer, "%-127s\n", temp); } pos = 128; save_flags(flags); cli(); for(idx = 0; idx < IP_MASQ_TAB_SIZE; idx++) for(ms = ip_masq_m_tab[idx]; ms ; ms = ms->m_link) { int timer_active; pos += 128; if (pos <= offset) continue; timer_active = del_timer(&ms->timer); if (!timer_active) ms->timer.expires = jiffies; sprintf(temp,"%s %08lX:%04X %08lX:%04X %04X %08X %6d %6d %7lu", masq_proto_name(ms->protocol), ntohl(ms->saddr), ntohs(ms->sport), ntohl(ms->daddr), ntohs(ms->dport), ntohs(ms->mport), ms->out_seq.init_seq, ms->out_seq.delta, ms->out_seq.previous_delta, ms->timer.expires-jiffies); if (timer_active) add_timer(&ms->timer); len += sprintf(buffer+len, "%-127s\n", temp); if(len >= length) goto done; } done: restore_flags(flags); begin = len - (pos - offset); *start = buffer + begin; len -= begin; if(len>length) len = length; return len; }
struct ip_masq * ip_masq_new_enh(struct device *dev, int proto, __u32 saddr, __u16 sport, __u32 daddr, __u16 dport, unsigned mflags, __u16 matchport) { struct ip_masq *ms, *mst; int ports_tried, *free_ports_p; unsigned long flags; static int n_fails = 0; free_ports_p = &ip_masq_free_ports[masq_proto_num(proto)]; if (*free_ports_p == 0) { if (++n_fails < 5) printk("ip_masq_new(proto=%s): no free ports.\n", masq_proto_name(proto)); return NULL; } ms = (struct ip_masq *) kmalloc(sizeof(struct ip_masq), GFP_ATOMIC); if (ms == NULL) { if (++n_fails < 5) printk("ip_masq_new(proto=%s): no memory available.\n", masq_proto_name(proto)); return NULL; } memset(ms, 0, sizeof(*ms)); init_timer(&ms->timer); ms->timer.data = (unsigned long)ms; ms->timer.function = masq_expire; ms->protocol = proto; ms->saddr = saddr; ms->sport = sport; ms->daddr = daddr; ms->dport = dport; ms->flags = mflags; ms->app_data = NULL; ms->control = NULL; if (proto == IPPROTO_UDP && !matchport) ms->flags |= IP_MASQ_F_NO_DADDR; /* get masq address from rif */ ms->maddr = dev->pa_addr; /* * Setup new entry as not replied yet. * This flag will allow masq. addr (ms->maddr) * to follow forwarding interface address. */ ms->flags |= IP_MASQ_F_NO_REPLY; for (ports_tried = 0; (*free_ports_p && (ports_tried <= (PORT_MASQ_END - PORT_MASQ_BEGIN))); ports_tried++){ save_flags(flags); cli(); /* * Try the next available port number */ if (!matchport || ports_tried) ms->mport = htons(masq_port++); else ms->mport = matchport; if (masq_port==PORT_MASQ_END) masq_port = PORT_MASQ_BEGIN; restore_flags(flags); /* * lookup to find out if this port is used. */ mst = ip_masq_getbym(proto, ms->maddr, ms->mport); if (mst == NULL || matchport) { save_flags(flags); cli(); if (*free_ports_p == 0) { restore_flags(flags); break; } (*free_ports_p)--; ip_masq_hash(ms); restore_flags(flags); if (proto != IPPROTO_ICMP) ip_masq_bind_app(ms); n_fails = 0; return ms; } } if (++n_fails < 5) printk("ip_masq_new(proto=%s): could not get free masq entry (free=%d).\n", masq_proto_name(ms->protocol), *free_ports_p); kfree_s(ms, sizeof(*ms)); return NULL; }
int isdn_tty_cmd_FCLASS1(char **p, modem_info * info) { static char *cmd[] = {"AE", "TS", "RS", "TM", "RM", "TH", "RH"}; isdn_ctrl c; int par, i; long flags; for (c.parm.aux.cmd = 0; c.parm.aux.cmd < 7; c.parm.aux.cmd++) if (!strncmp(p[0], cmd[c.parm.aux.cmd], 2)) break; #ifdef ISDN_TTY_FAX_CMD_DEBUG printk(KERN_DEBUG "isdn_tty_cmd_FCLASS1 (%s,%d)\n", p[0], c.parm.aux.cmd); #endif if (c.parm.aux.cmd == 7) PARSE_ERROR1; p[0] += 2; switch (*p[0]) { case '?': p[0]++; c.parm.aux.subcmd = AT_QUERY; break; case '=': p[0]++; if (*p[0] == '?') { p[0]++; c.parm.aux.subcmd = AT_EQ_QUERY; } else { par = isdn_getnum(p); if ((par < 0) || (par > 255)) PARSE_ERROR1; c.parm.aux.subcmd = AT_EQ_VALUE; c.parm.aux.para[0] = par; } break; case 0: c.parm.aux.subcmd = AT_COMMAND; break; default: PARSE_ERROR1; } c.command = ISDN_CMD_FAXCMD; #ifdef ISDN_TTY_FAX_CMD_DEBUG printk(KERN_DEBUG "isdn_tty_cmd_FCLASS1 %d/%d/%d)\n", c.parm.aux.cmd, c.parm.aux.subcmd, c.parm.aux.para[0]); #endif if (info->isdn_driver < 0) { save_flags(flags); cli(); if ((c.parm.aux.subcmd == AT_EQ_VALUE) || (c.parm.aux.subcmd == AT_COMMAND)) { restore_flags(flags); PARSE_ERROR1; } /* get a temporary connection to the first free fax driver */ i = isdn_get_free_channel(ISDN_USAGE_FAX, ISDN_PROTO_L2_FAX, ISDN_PROTO_L3_FCLASS1, -1, -1, "00"); if (i < 0) { restore_flags(flags); PARSE_ERROR1; } info->isdn_driver = dev->drvmap[i]; info->isdn_channel = dev->chanmap[i]; info->drv_index = i; dev->m_idx[i] = info->line; c.driver = info->isdn_driver; c.arg = info->isdn_channel; isdn_command(&c); isdn_free_channel(info->isdn_driver, info->isdn_channel, ISDN_USAGE_FAX); info->isdn_driver = -1; info->isdn_channel = -1; if (info->drv_index >= 0) { dev->m_idx[info->drv_index] = -1; info->drv_index = -1; } restore_flags(flags); } else { c.driver = info->isdn_driver; c.arg = info->isdn_channel; isdn_command(&c); } return 1; }
/* Output a cmd_len long command string to the FDC. * The FDC should be ready to receive a new command or * an error (EBUSY or ETIME) will occur. */ int fdc_command(const __u8 * cmd_data, int cmd_len) { int result = 0; unsigned long flags; int count = cmd_len; int retry = 0; #ifdef TESTING static unsigned int last_time; unsigned int time; #endif TRACE_FUN(ft_t_any); fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */ spin_lock_irqsave(&fdc_io_lock, flags); if (!in_interrupt()) /* Yes, I know, too much comments inside this function * ... * * Yet another bug in the original driver. All that * havoc is caused by the fact that the isr() sends * itself a command to the floppy tape driver (pause, * micro step pause). Now, the problem is that * commands are transmitted via the fdc_seek * command. But: the fdc performs seeks in the * background i.e. it doesn't signal busy while * sending the step pulses to the drive. Therefore the * non-interrupt level driver has no chance to tell * whether the isr() just has issued a seek. Therefore * we HAVE TO have a look at the ft_hide_interrupt * flag: it signals the non-interrupt level part of * the driver that it has to wait for the fdc until it * has completet seeking. * * THIS WAS PRESUMABLY THE REASON FOR ALL THAT * "fdc_read timeout" errors, I HOPE :-) */ if (ft_hide_interrupt) { restore_flags(flags); TRACE(ft_t_info, "Waiting for the isr() completing fdc_seek()"); if (fdc_interrupt_wait(2 * FT_SECOND) < 0) { TRACE(ft_t_warn, "Warning: timeout waiting for isr() seek to complete"); } if (ft_hide_interrupt || !ft_seek_completed) { /* There cannot be another * interrupt. The isr() only stops * the tape and the next interrupt * won't come until we have send our * command to the drive. */ TRACE_ABORT(-EIO, ft_t_bug, "BUG? isr() is still seeking?\n" KERN_INFO "hide: %d\n" KERN_INFO "seek: %d", ft_hide_interrupt, ft_seek_completed); } fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */ spin_lock_irqsave(&fdc_io_lock, flags); } fdc_status = inb(fdc.msr); if ((fdc_status & FDC_DATA_READY_MASK) != FDC_DATA_IN_READY) { spin_unlock_irqrestore(&fdc_io_lock, flags); TRACE_ABORT(-EBUSY, ft_t_err, "fdc not ready"); } fdc_mode = *cmd_data; /* used by isr */ #ifdef TESTING if (fdc_mode == FDC_SEEK) { time = ftape_timediff(last_time, ftape_timestamp()); if (time < 6000) { TRACE(ft_t_bug,"Warning: short timeout between seek commands: %d", time); } } #endif if (!in_interrupt()) { /* shouldn't be cleared if called from isr */ ft_interrupt_seen = 0; } while (count) { result = fdc_write(*cmd_data); if (result < 0) { TRACE(ft_t_fdc_dma, "fdc_mode = %02x, status = %02x at index %d", (int) fdc_mode, (int) fdc_status, cmd_len - count); if (++retry <= 3) { TRACE(ft_t_warn, "fdc_write timeout, retry"); } else { TRACE(ft_t_err, "fdc_write timeout, fatal"); /* recover ??? */ break; } } else { --count; ++cmd_data; } } #ifdef TESTING if (fdc_mode == FDC_SEEK) { last_time = ftape_timestamp(); } #endif spin_unlock_irqrestore(&fdc_io_lock, flags); TRACE_EXIT result; }
void atari_free_irq(unsigned int irq, void *dev_id) { unsigned long flags; int vector; irq_node_t **list, *node; if (!IS_VALID_INTNO(irq)) { printk("%s: Unknown irq %d\n", __FUNCTION__, irq); return; } vector = IRQ_SOURCE_TO_VECTOR(irq); if (vectors[vector] == bad_interrupt) goto not_found; save_flags(flags); cli(); if (irq_handler[irq].handler != atari_call_irq_list) { /* It's the only handler for the interrupt */ if (irq_handler[irq].dev_id != dev_id) { restore_flags(flags); goto not_found; } irq_handler[irq].handler = NULL; irq_handler[irq].dev_id = NULL; irq_param[irq].devname = NULL; vectors[vector] = bad_interrupt; /* If MFP int, also disable it */ atari_disable_irq(irq); atari_turnoff_irq(irq); restore_flags(flags); return; } /* The interrupt is chained, find the irq on the list */ for(list = (irq_node_t **)&irq_handler[irq].dev_id; *list; list = &(*list)->next) { if ((*list)->dev_id == dev_id) break; } if (!*list) { restore_flags(flags); goto not_found; } (*list)->handler = NULL; /* Mark it as free for reallocation */ *list = (*list)->next; /* If there's now only one handler, unchain the interrupt, i.e. plug in * the handler directly again and omit atari_call_irq_list */ node = (irq_node_t *)irq_handler[irq].dev_id; if (node && !node->next) { irq_handler[irq].handler = node->handler; irq_handler[irq].dev_id = node->dev_id; irq_param[irq].devname = node->devname; node->handler = NULL; /* Mark it as free for reallocation */ } restore_flags(flags); return; not_found: printk("%s: tried to remove invalid irq\n", __FUNCTION__); return; }
int atari_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id) { int vector; unsigned long oflags = flags; /* * The following is a hack to make some PCI card drivers work, * which set the SA_SHIRQ flag. */ flags &= ~SA_SHIRQ; if (flags == SA_INTERRUPT) { printk ("%s: SA_INTERRUPT changed to IRQ_TYPE_SLOW for %s\n", __FUNCTION__, devname); flags = IRQ_TYPE_SLOW; } if (flags < IRQ_TYPE_SLOW || flags > IRQ_TYPE_PRIO) { printk ("%s: Bad irq type 0x%lx <0x%lx> requested from %s\n", __FUNCTION__, flags, oflags, devname); return -EINVAL; } if (!IS_VALID_INTNO(irq)) { printk ("%s: Unknown irq %d requested from %s\n", __FUNCTION__, irq, devname); return -ENXIO; } vector = IRQ_SOURCE_TO_VECTOR(irq); /* * Check type/source combination: slow ints are (currently) * only possible for MFP-interrupts. */ if (flags == IRQ_TYPE_SLOW && (irq < STMFP_SOURCE_BASE || irq >= SCC_SOURCE_BASE)) { printk ("%s: Slow irq requested for non-MFP source %d from %s\n", __FUNCTION__, irq, devname); return -EINVAL; } if (vectors[vector] == bad_interrupt) { /* int has no handler yet */ irq_handler[irq].handler = handler; irq_handler[irq].dev_id = dev_id; irq_param[irq].flags = flags; irq_param[irq].devname = devname; vectors[vector] = (flags == IRQ_TYPE_SLOW) ? slow_handlers[irq-STMFP_SOURCE_BASE] : (flags == IRQ_TYPE_FAST) ? atari_fast_irq_handler : atari_prio_irq_handler; /* If MFP int, also enable and umask it */ atari_turnon_irq(irq); atari_enable_irq(irq); return 0; } else if (irq_param[irq].flags == flags) { /* old handler is of same type -> handlers can be chained */ irq_node_t *node; unsigned long flags; save_flags(flags); cli(); if (irq_handler[irq].handler != atari_call_irq_list) { /* Only one handler yet, make a node for this first one */ if (!(node = new_irq_node())) return -ENOMEM; node->handler = irq_handler[irq].handler; node->dev_id = irq_handler[irq].dev_id; node->devname = irq_param[irq].devname; node->next = NULL; irq_handler[irq].handler = atari_call_irq_list; irq_handler[irq].dev_id = node; irq_param[irq].devname = "chained"; } if (!(node = new_irq_node())) return -ENOMEM; node->handler = handler; node->dev_id = dev_id; node->devname = devname; /* new handlers are put in front of the queue */ node->next = irq_handler[irq].dev_id; irq_handler[irq].dev_id = node; restore_flags(flags); return 0; } else { printk ("%s: Irq %d allocated by other type int (call from %s)\n", __FUNCTION__, irq, devname); return -EBUSY; } }
static void ambauart_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot) { u_int lcr, old_ier, fcr=0; unsigned long flags; #if DEBUG printk("ambauart_set_cflag(0x%x) called\n", cflag); #endif //printk("ambauart_change_speed\n"); /* byte size and parity */ switch (cflag & CSIZE) { case CS5: lcr = KS8695_UART_LINEC_WLEN5; break; case CS6: lcr = KS8695_UART_LINEC_WLEN6; break; case CS7: lcr = KS8695_UART_LINEC_WLEN7; break; default: lcr = KS8695_UART_LINEC_WLEN8; break; // CS8 } if (cflag & CSTOPB) lcr |= KS8695_UART_LINEC_STP2; if (cflag & PARENB) { lcr |= KS8695_UART_LINEC_PEN; if (!(cflag & PARODD)) lcr |= KS8695_UART_LINEC_EPS; } if (port->fifosize > 1) fcr = KS8695_UART_FIFO_TRIG04 | KS8695_UART_FIFO_TXRST | KS8695_UART_FIFO_RXRST | KS8695_UART_FIFO_FEN; port->read_status_mask = KS8695_UART_LINES_OE; if (iflag & INPCK) port->read_status_mask |= (KS8695_UART_LINES_FE | KS8695_UART_LINES_PE); if (iflag & (BRKINT | PARMRK)) port->read_status_mask |= KS8695_UART_LINES_BE; /* * Characters to ignore */ port->ignore_status_mask = 0; if (iflag & IGNPAR) port->ignore_status_mask |= (KS8695_UART_LINES_FE | KS8695_UART_LINES_PE); if (iflag & IGNBRK) { port->ignore_status_mask |= KS8695_UART_LINES_BE; /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (iflag & IGNPAR) port->ignore_status_mask |= KS8695_UART_LINES_OE; } /* * Ignore all characters if CREAD is not set. */ if ((cflag & CREAD) == 0) port->ignore_status_mask |= UART_DUMMY_LSR_RX; /* first, disable everything */ save_flags(flags); cli(); old_ier = UART_GET_IER(port); UART_PUT_IER(port, old_ier & 0xFFFFF0FF); old_ier &= ~KS8695_INT_ENABLE_MODEM; if ((port->flags & ASYNC_HARDPPS_CD) || (cflag & CRTSCTS) || !(cflag & CLOCAL)) old_ier |= KS8695_INT_ENABLE_MODEM; /* Set baud rate */ // UART_PUT_BRDR(port, port->uartclk / quot); UART_PUT_BRDR(port, 0x28B); UART_PUT_LCR(port, lcr); UART_PUT_FCR(port, fcr); UART_PUT_IER(port, old_ier & 0xFFFFFEFF); restore_flags(flags); }
int cf_command(int drvid, int mode, u_char proc, char *msn, u_char service, char *fwd_nr, ulong *procid) { int retval,msnlen,flags; int fwd_len; char *p,*ielenp,tmp[60]; struct call_struc *cs; if (strchr(msn,'.')) return(-EINVAL); /* subaddress not allowed in msn */ if ((proc & 0x7F) > 2) return(-EINVAL); proc &= 3; p = tmp; *p++ = 0x30; /* enumeration */ ielenp = p++; /* remember total length position */ *p++ = 0xa; /* proc tag */ *p++ = 1; /* length */ *p++ = proc & 0x7F; /* procedure to de/activate/interrogate */ *p++ = 0xa; /* service tag */ *p++ = 1; /* length */ *p++ = service; /* service to handle */ if (mode == 1) { if (!*fwd_nr) return(-EINVAL); /* destination missing */ if (strchr(fwd_nr,'.')) return(-EINVAL); /* subaddress not allowed */ fwd_len = strlen(fwd_nr); *p++ = 0x30; /* number enumeration */ *p++ = fwd_len + 2; /* complete forward to len */ *p++ = 0x80; /* fwd to nr */ *p++ = fwd_len; /* length of number */ strcpy(p,fwd_nr); /* copy number */ p += fwd_len; /* pointer beyond fwd */ } /* activate */ msnlen = strlen(msn); *p++ = 0x80; /* msn number */ if (msnlen > 1) { *p++ = msnlen; /* length */ strcpy(p,msn); p += msnlen; } else *p++ = 0; *ielenp = p - ielenp - 1; /* set total IE length */ /* allocate mem for information struct */ if (!(cs = (struct call_struc *) kmalloc(sizeof(struct call_struc), GFP_ATOMIC))) return(-ENOMEM); /* no memory */ init_timer(&cs->timer); cs->info[0] = '\0'; cs->timer.function = deflect_timer_expire; cs->timer.data = (ulong) cs; /* pointer to own structure */ cs->ics.driver = drvid; cs->ics.command = ISDN_CMD_PROT_IO; /* protocol specific io */ cs->ics.arg = DSS1_CMD_INVOKE; /* invoke supplementary service */ cs->ics.parm.dss1_io.proc = (mode == 1) ? 7: (mode == 2) ? 11:8; /* operation */ cs->ics.parm.dss1_io.timeout = 4000; /* from ETS 300 207-1 */ cs->ics.parm.dss1_io.datalen = p - tmp; /* total len */ cs->ics.parm.dss1_io.data = tmp; /* start of buffer */ save_flags(flags); cli(); cs->ics.parm.dss1_io.ll_id = next_id++; /* id for callback */ restore_flags(flags); *procid = cs->ics.parm.dss1_io.ll_id; sprintf(cs->info,"%d 0x%lx %s%s 0 %s %0x %d%s%s\n", (!mode ) ? DIVERT_DEACTIVATE : (mode == 1) ? DIVERT_ACTIVATE : DIVERT_REPORT, cs->ics.parm.dss1_io.ll_id, (mode != 2) ? "" : "0 ", divert_if.drv_to_name(cs->ics.driver), msn, service & 0xFF, proc, (mode != 1) ? "" : " 0 ", (mode != 1) ? "" : fwd_nr); retval = divert_if.ll_cmd(&cs->ics); /* excute command */ if (!retval) { cs->prev = NULL; save_flags(flags); cli(); cs->next = divert_head; divert_head = cs; restore_flags(flags); } else kfree(cs); return(retval); } /* cf_command */
int ip_fw_masquerade(struct sk_buff **skb_ptr, struct device *dev) { struct sk_buff *skb=*skb_ptr; struct iphdr *iph = skb->h.iph; __u16 *portptr; struct ip_masq *ms; int size; unsigned long timeout; /* * We can only masquerade protocols with ports... * [TODO] * We may need to consider masq-ing some ICMP related to masq-ed protocols */ if (iph->protocol==IPPROTO_ICMP) return (ip_fw_masq_icmp(skb_ptr,dev)); if (iph->protocol!=IPPROTO_UDP && iph->protocol!=IPPROTO_TCP) return -1; /* * Now hunt the list to see if we have an old entry */ portptr = (__u16 *)&(((char *)iph)[iph->ihl*4]); #ifdef DEBUG_CONFIG_IP_MASQUERADE printk("Outgoing %s %lX:%X -> %lX:%X\n", masq_proto_name(iph->protocol), ntohl(iph->saddr), ntohs(portptr[0]), ntohl(iph->daddr), ntohs(portptr[1])); #endif ms = ip_masq_out_get(iph); if (ms!=NULL) { ip_masq_set_expire(ms,0); /* * If sysctl !=0 and no pkt has been received yet * in this tunnel and routing iface address has changed... * "You are welcome, diald". */ if ( sysctl_ip_dynaddr && ms->flags & IP_MASQ_F_NO_REPLY && dev->pa_addr != ms->maddr) { unsigned long flags; if (sysctl_ip_dynaddr > 1) { printk(KERN_INFO "ip_fw_masquerade(): change maddr from %s", in_ntoa(ms->maddr)); printk(" to %s\n", in_ntoa(dev->pa_addr)); } save_flags(flags); cli(); ip_masq_unhash(ms); ms->maddr = dev->pa_addr; ip_masq_hash(ms); restore_flags(flags); } /* * Set sport if not defined yet (e.g. ftp PASV). Because * masq entries are hashed on sport, unhash with old value * and hash with new. */ if ( ms->flags & IP_MASQ_F_NO_SPORT && ms->protocol == IPPROTO_TCP ) { unsigned long flags; ms->flags &= ~IP_MASQ_F_NO_SPORT; save_flags(flags); cli(); ip_masq_unhash(ms); ms->sport = portptr[0]; ip_masq_hash(ms); /* hash on new sport */ restore_flags(flags); #ifdef DEBUG_CONFIG_IP_MASQUERADE printk("ip_fw_masquerade(): filled sport=%d\n", ntohs(ms->sport)); #endif } } #ifdef CONFIG_IP_MASQUERADE_IPAUTOFW /* update any ipautofw entries .. */ ip_autofw_update_out(iph->saddr, iph->daddr, portptr[1], iph->protocol); #endif /* CONFIG_IP_MASQUERADE_IPAUTOFW */ /* * Nope, not found, create a new entry for it */ if (ms==NULL) { #ifdef CONFIG_IP_MASQUERADE_IPAUTOFW /* if the source port is supposed to match the masq port, then make it so */ if (ip_autofw_check_direct(portptr[1],iph->protocol)) ms = ip_masq_new_enh(dev, iph->protocol, iph->saddr, portptr[0], iph->daddr, portptr[1], 0, portptr[0]); else #endif /* CONFIG_IP_MASQUERADE_IPAUTOFW */ ms = ip_masq_new_enh(dev, iph->protocol, iph->saddr, portptr[0], iph->daddr, portptr[1], 0, 0); if (ms == NULL) return -1; } /* * Change the fragments origin */ size = skb->len - ((unsigned char *)portptr - skb->h.raw); /* * Set iph addr and port from ip_masq obj. */ iph->saddr = ms->maddr; portptr[0] = ms->mport; /* * Attempt ip_masq_app call. * will fix ip_masq and iph seq stuff */ if (ip_masq_app_pkt_out(ms, skb_ptr, dev) != 0) { /* * skb has possibly changed, update pointers. */ skb = *skb_ptr; iph = skb->h.iph; portptr = (__u16 *)&(((char *)iph)[iph->ihl*4]); size = skb->len - ((unsigned char *)portptr-skb->h.raw); } /* * Adjust packet accordingly to protocol */ if (masq_proto_num(iph->protocol)==0) { timeout = ip_masq_expire->udp_timeout; recalc_check((struct udphdr *)portptr,iph->saddr,iph->daddr,size); } else { struct tcphdr *th; th = (struct tcphdr *)portptr; /* Set the flags up correctly... */ if (th->fin) { ms->flags |= IP_MASQ_F_SAW_FIN_OUT; } if (th->rst) { ms->flags |= IP_MASQ_F_SAW_RST; } /* * Timeout depends if FIN packet has been seen * Very short timeout if RST packet seen. */ if (ms->flags & IP_MASQ_F_SAW_RST) { timeout = 1; } else if ((ms->flags & IP_MASQ_F_SAW_FIN) == IP_MASQ_F_SAW_FIN) { timeout = ip_masq_expire->tcp_fin_timeout; } else timeout = ip_masq_expire->tcp_timeout; skb->csum = csum_partial((void *)(th + 1), size - sizeof(*th), 0); tcp_send_check(th,iph->saddr,iph->daddr,size,skb); } ip_masq_set_expire(ms, timeout); ip_send_check(iph); #ifdef DEBUG_CONFIG_IP_MASQUERADE printk("O-routed from %lX:%X over %s\n",ntohl(ms->maddr),ntohs(ms->mport),dev->name); #endif return 0; }
int deflect_extern_action(u_char cmd, ulong callid, char *to_nr) { struct call_struc *cs; isdn_ctrl ic; int flags; int i; if ((cmd & 0x7F) > 2) return(-EINVAL); /* invalid command */ cs = divert_head; /* start of parameter list */ while (cs) { if (cs->divert_id == callid) break; /* found */ cs = cs->next; } /* search entry */ if (!cs) return(-EINVAL); /* invalid callid */ ic.driver = cs->ics.driver; ic.arg = cs->ics.arg; i = -EINVAL; if (cs->akt_state == DEFLECT_AUTODEL) return(i); /* no valid call */ switch (cmd & 0x7F) { case 0: /* hangup */ del_timer(&cs->timer); ic.command = ISDN_CMD_HANGUP; i = divert_if.ll_cmd(&ic); save_flags(flags); cli(); cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); add_timer(&cs->timer); restore_flags(flags); break; case 1: /* alert */ if (cs->akt_state == DEFLECT_ALERT) return(0); cmd &= 0x7F; /* never wait */ del_timer(&cs->timer); ic.command = ISDN_CMD_ALERT; if ((i = divert_if.ll_cmd(&ic))) { save_flags(flags); cli(); cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); add_timer(&cs->timer); restore_flags(flags); } else cs->akt_state = DEFLECT_ALERT; break; case 2: /* redir */ del_timer(&cs->timer); strcpy(cs->ics.parm.setup.phone, to_nr); strcpy(cs->ics.parm.setup.eazmsn, "Testtext manual"); ic.command = ISDN_CMD_REDIR; if ((i = divert_if.ll_cmd(&ic))) { save_flags(flags); cli(); cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); add_timer(&cs->timer); restore_flags(flags); } else cs->akt_state = DEFLECT_ALERT; break; } /* switch */ return(i); } /* deflect_extern_action */
int ip_fw_masq_icmp(struct sk_buff **skb_p, struct device *dev) { struct sk_buff *skb = *skb_p; struct iphdr *iph = skb->h.iph; struct icmphdr *icmph = (struct icmphdr *)((char *)iph + (iph->ihl<<2)); struct iphdr *ciph; /* The ip header contained within the ICMP */ __u16 *pptr; /* port numbers from TCP/UDP contained header */ struct ip_masq *ms; unsigned short len = ntohs(iph->tot_len) - (iph->ihl * 4); #ifdef DEBUG_CONFIG_IP_MASQUERADE_ICMP printk("Incoming forward ICMP (%d,%d) %lX -> %lX\n", icmph->type, ntohs(icmp_id(icmph)), ntohl(iph->saddr), ntohl(iph->daddr)); #endif #ifdef CONFIG_IP_MASQUERADE_ICMP if ((icmph->type == ICMP_ECHO ) || (icmph->type == ICMP_TIMESTAMP ) || (icmph->type == ICMP_INFO_REQUEST ) || (icmph->type == ICMP_ADDRESS )) { #ifdef DEBUG_CONFIG_IP_MASQUERADE_ICMP printk("MASQ: icmp request rcv %lX->%lX id %d type %d\n", ntohl(iph->saddr), ntohl(iph->daddr), ntohs(icmp_id(icmph)), icmph->type); #endif ms = ip_masq_out_get_2(iph->protocol, iph->saddr, icmp_id(icmph), iph->daddr, icmp_hv_req(icmph)); if (ms == NULL) { ms = ip_masq_new(dev, iph->protocol, iph->saddr, icmp_id(icmph), iph->daddr, icmp_hv_req(icmph), 0); if (ms == NULL) return (-1); #ifdef DEBUG_CONFIG_IP_MASQUERADE_ICMP printk("MASQ: Create new icmp entry\n"); #endif } ip_masq_set_expire(ms, 0); /* Rewrite source address */ /* * If sysctl !=0 and no pkt has been received yet * in this tunnel and routing iface address has changed... * "You are welcome, diald". */ if ( sysctl_ip_dynaddr && ms->flags & IP_MASQ_F_NO_REPLY && dev->pa_addr != ms->maddr) { unsigned long flags; #ifdef DEBUG_CONFIG_IP_MASQUERADE printk(KERN_INFO "ip_fw_masq_icmp(): change masq.addr %s", in_ntoa(ms->maddr)); printk("-> %s\n", in_ntoa(dev->pa_addr)); #endif save_flags(flags); cli(); ip_masq_unhash(ms); ms->maddr = dev->pa_addr; ip_masq_hash(ms); restore_flags(flags); } iph->saddr = ms->maddr; ip_send_check(iph); /* Rewrite port (id) */ (icmph->un).echo.id = ms->mport; icmph->checksum = 0; icmph->checksum = ip_compute_csum((unsigned char *)icmph, len); ip_masq_set_expire(ms, MASQUERADE_EXPIRE_ICMP); #ifdef DEBUG_CONFIG_IP_MASQUERADE_ICMP printk("MASQ: icmp request rwt %lX->%lX id %d type %d\n", ntohl(iph->saddr), ntohl(iph->daddr), ntohs(icmp_id(icmph)), icmph->type); #endif return (1); } #endif /* * Work through seeing if this is for us. * These checks are supposed to be in an order that * means easy things are checked first to speed up * processing.... however this means that some * packets will manage to get a long way down this * stack and then be rejected, but thats life */ if ((icmph->type != ICMP_DEST_UNREACH) && (icmph->type != ICMP_SOURCE_QUENCH) && (icmph->type != ICMP_TIME_EXCEEDED)) return 0; /* Now find the contained IP header */ ciph = (struct iphdr *) (icmph + 1); #ifdef CONFIG_IP_MASQUERADE_ICMP if (ciph->protocol == IPPROTO_ICMP) { /* * This section handles ICMP errors for ICMP packets */ struct icmphdr *cicmph = (struct icmphdr *)((char *)ciph + (ciph->ihl<<2)); #ifdef DEBUG_CONFIG_IP_MASQUERADE_ICMP printk("MASQ: fw icmp/icmp rcv %lX->%lX id %d type %d\n", ntohl(ciph->saddr), ntohl(ciph->daddr), ntohs(icmp_id(cicmph)), cicmph->type); #endif ms = ip_masq_out_get_2(ciph->protocol, ciph->daddr, icmp_id(cicmph), ciph->saddr, icmp_hv_rep(cicmph)); if (ms == NULL) return 0; /* Now we do real damage to this packet...! */ /* First change the source IP address, and recalc checksum */ iph->saddr = ms->maddr; ip_send_check(iph); /* Now change the *dest* address in the contained IP */ ciph->daddr = ms->maddr; ip_send_check(ciph); /* Change the ID to the masqed one! */ (cicmph->un).echo.id = ms->mport; /* And finally the ICMP checksum */ icmph->checksum = 0; icmph->checksum = ip_compute_csum((unsigned char *) icmph, len); #ifdef DEBUG_CONFIG_IP_MASQUERADE_ICMP printk("MASQ: fw icmp/icmp rwt %lX->%lX id %d type %d\n", ntohl(ciph->saddr), ntohl(ciph->daddr), ntohs(icmp_id(cicmph)), cicmph->type); #endif return 1; } #endif /* CONFIG_IP_MASQUERADE_ICMP */ /* We are only interested ICMPs generated from TCP or UDP packets */ if ((ciph->protocol != IPPROTO_UDP) && (ciph->protocol != IPPROTO_TCP)) return 0; /* * Find the ports involved - this packet was * incoming so the ports are right way round * (but reversed relative to outer IP header!) */ pptr = (__u16 *)&(((char *)ciph)[ciph->ihl*4]); /* Ensure the checksum is correct */ if (ip_compute_csum((unsigned char *) icmph, len)) { /* Failed checksum! */ printk(KERN_DEBUG "MASQ: forward ICMP: failed checksum from %s!\n", in_ntoa(iph->saddr)); return(-1); } #ifdef DEBUG_CONFIG_IP_MASQUERADE printk("Handling forward ICMP for %lX:%X -> %lX:%X\n", ntohl(ciph->saddr), ntohs(pptr[0]), ntohl(ciph->daddr), ntohs(pptr[1])); #endif /* This is pretty much what ip_masq_out_get() does */ ms = ip_masq_out_get_2(ciph->protocol, ciph->daddr, pptr[1], ciph->saddr, pptr[0]); if (ms == NULL) return 0; /* Now we do real damage to this packet...! */ /* First change the source IP address, and recalc checksum */ iph->saddr = ms->maddr; ip_send_check(iph); /* Now change the *dest* address in the contained IP */ ciph->daddr = ms->maddr; ip_send_check(ciph); /* the TCP/UDP dest port - cannot redo check */ pptr[1] = ms->mport; /* And finally the ICMP checksum */ icmph->checksum = 0; icmph->checksum = ip_compute_csum((unsigned char *) icmph, len); #ifdef DEBUG_CONFIG_IP_MASQUERADE printk("Rewrote forward ICMP to %lX:%X -> %lX:%X\n", ntohl(ciph->saddr), ntohs(pptr[0]), ntohl(ciph->daddr), ntohs(pptr[1])); #endif return 1; }
int prot_stat_callback(isdn_ctrl *ic) { struct call_struc *cs, *cs1; int i,flags; cs = divert_head; /* start of list */ cs1 = NULL; while (cs) { if (ic->driver == cs->ics.driver) { switch (cs->ics.arg) { case DSS1_CMD_INVOKE: if ((cs->ics.parm.dss1_io.ll_id == ic->parm.dss1_io.ll_id) && (cs->ics.parm.dss1_io.hl_id == ic->parm.dss1_io.hl_id)) { switch (ic->arg) { case DSS1_STAT_INVOKE_ERR: sprintf(cs->info,"128 0x%lx 0x%x\n", ic->parm.dss1_io.ll_id, ic->parm.dss1_io.timeout); put_info_buffer(cs->info); break; case DSS1_STAT_INVOKE_RES: switch (cs->ics.parm.dss1_io.proc) { case 7: case 8: put_info_buffer(cs->info); break; case 11: i = interrogate_success(ic,cs); if (i) sprintf(cs->info,"%d 0x%lx %d\n",DIVERT_REPORT, ic->parm.dss1_io.ll_id,i); put_info_buffer(cs->info); break; default: printk(KERN_WARNING "dss1_divert: unknown proc %d\n",cs->ics.parm.dss1_io.proc); break; } break; default: printk(KERN_WARNING "dss1_divert unknown invoke answer %lx\n",ic->arg); break; } cs1 = cs; /* remember structure */ cs = NULL; continue; /* abort search */ } /* id found */ break; case DSS1_CMD_INVOKE_ABORT: printk(KERN_WARNING "dss1_divert unhandled invoke abort\n"); break; default: printk(KERN_WARNING "dss1_divert unknown cmd 0x%lx\n",cs->ics.arg); break; } /* switch ics.arg */ cs = cs->next; } /* driver ok */ } if (!cs1) { printk(KERN_WARNING "dss1_divert unhandled process\n"); return(0); } if (cs1->ics.driver == -1) { save_flags(flags); cli(); del_timer(&cs1->timer); if (cs1->prev) cs1->prev->next = cs1->next; /* forward link */ else divert_head = cs1->next; if (cs1->next) cs1->next->prev = cs1->prev; /* back link */ restore_flags(flags); kfree(cs1); } return(0); } /* prot_stat_callback */
static int isdn_divert_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) { divert_ioctl dioctl; int i; unsigned long flags; divert_rule *rulep; char *cp; if ((i = copy_from_user(&dioctl, (char *) arg, sizeof(dioctl)))) return (i); switch (cmd) { case IIOCGETVER: dioctl.drv_version = DIVERT_IIOC_VERSION; /* set version */ break; case IIOCGETDRV: if ((dioctl.getid.drvid = divert_if.name_to_drv(dioctl.getid.drvnam)) < 0) return (-EINVAL); break; case IIOCGETNAM: cp = divert_if.drv_to_name(dioctl.getid.drvid); if (!cp) return (-EINVAL); if (!*cp) return (-EINVAL); strcpy(dioctl.getid.drvnam, cp); break; case IIOCGETRULE: if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx))) return (-EINVAL); dioctl.getsetrule.rule = *rulep; /* copy data */ break; case IIOCMODRULE: if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx))) return (-EINVAL); save_flags(flags); cli(); *rulep = dioctl.getsetrule.rule; /* copy data */ restore_flags(flags); return (0); /* no copy required */ break; case IIOCINSRULE: return (insertrule(dioctl.getsetrule.ruleidx, &dioctl.getsetrule.rule)); break; case IIOCDELRULE: return (deleterule(dioctl.getsetrule.ruleidx)); break; case IIOCDODFACT: return (deflect_extern_action(dioctl.fwd_ctrl.subcmd, dioctl.fwd_ctrl.callid, dioctl.fwd_ctrl.to_nr)); case IIOCDOCFACT: case IIOCDOCFDIS: case IIOCDOCFINT: if (!divert_if.drv_to_name(dioctl.cf_ctrl.drvid)) return (-EINVAL); /* invalid driver */ if ((i = cf_command(dioctl.cf_ctrl.drvid, (cmd == IIOCDOCFACT) ? 1 : (cmd == IIOCDOCFDIS) ? 0 : 2, dioctl.cf_ctrl.cfproc, dioctl.cf_ctrl.msn, dioctl.cf_ctrl.service, dioctl.cf_ctrl.fwd_nr, &dioctl.cf_ctrl.procid))) return (i); break; default: return (-EINVAL); } /* switch cmd */ return (copy_to_user((char *) arg, &dioctl, sizeof(dioctl))); /* success */ } /* isdn_divert_ioctl */
/* * Try finding a listener for an outgoing call. * * Parameter: * card = pointer to calling card. * p = pointer to ICN-type setup-string. * lch = channel of calling card. * cmd = pointer to struct to be filled when parsing setup. * Return: * 0 = found match, alerting should happen. * 1 = found matching number but it is busy. * 2 = no matching listener. * 3 = found matching number but SI does not match. */ static int isdnloop_try_call(isdnloop_card * card, char *p, int lch, isdn_ctrl * cmd) { isdnloop_card *cc = cards; unsigned long flags; int ch; int num_match; int i; char *e; char nbuf[32]; isdnloop_parse_setup(p, cmd); while (cc) { for (ch = 0; ch < 2; ch++) { /* Exclude ourself */ if ((cc == card) && (ch == lch)) continue; num_match = 0; switch (cc->ptype) { case ISDN_PTYPE_EURO: for (i = 0; i < 3; i++) if (!(strcmp(cc->s0num[i], cmd->parm.setup.phone))) num_match = 1; break; case ISDN_PTYPE_1TR6: e = cc->eazlist[ch]; while (*e) { sprintf(nbuf, "%s%c", cc->s0num[0], *e); if (!(strcmp(nbuf, cmd->parm.setup.phone))) num_match = 1; e++; } } if (num_match) { save_flags(flags); cli(); /* channel idle? */ if (!(cc->rcard[ch])) { /* Check SI */ if (!(si2bit[cmd->parm.setup.si1] & cc->sil[ch])) { restore_flags(flags); return 3; } /* ch is idle, si and number matches */ cc->rcard[ch] = card; cc->rch[ch] = lch; card->rcard[lch] = cc; card->rch[lch] = ch; restore_flags(flags); return 0; } else { restore_flags(flags); /* num matches, but busy */ if (ch == 1) return 1; } } } cc = cc->next; } return 2; }
/* rs_init inits the driver */ static int __init rs_nios_init(void) { int flags; struct NIOS_serial *info; int i; /* Setup base handler, and timer table. */ init_bh(SERIAL_BH, do_serial_bh); show_serial_version(); /* Initialize the tty_driver structure */ /* SPARC: Not all of this is exactly right for us. */ memset(&serial_driver, 0, sizeof(struct tty_driver)); serial_driver.magic = TTY_DRIVER_MAGIC; serial_driver.name = "ttyS"; serial_driver.major = TTY_MAJOR; serial_driver.minor_start = 64; serial_driver.num = NR_PORTS; serial_driver.type = TTY_DRIVER_TYPE_SERIAL; serial_driver.subtype = SERIAL_TYPE_NORMAL; serial_driver.init_termios = tty_std_termios; serial_driver.init_termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL; serial_driver.flags = TTY_DRIVER_REAL_RAW; serial_driver.refcount = &serial_refcount; serial_driver.table = serial_table; serial_driver.termios = serial_termios; serial_driver.termios_locked = serial_termios_locked; serial_driver.open = rs_open; serial_driver.close = rs_close; serial_driver.write = rs_write; serial_driver.flush_chars = rs_flush_chars; serial_driver.write_room = rs_write_room; serial_driver.chars_in_buffer = rs_chars_in_buffer; serial_driver.flush_buffer = rs_flush_buffer; serial_driver.ioctl = rs_ioctl; serial_driver.throttle = rs_throttle; serial_driver.unthrottle = rs_unthrottle; serial_driver.set_termios = rs_set_termios; serial_driver.stop = rs_stop; serial_driver.start = rs_start; serial_driver.hangup = rs_hangup; serial_driver.set_ldisc = rs_set_ldisc; /* * The callout device is just like normal device except for * major number and the subtype code. */ callout_driver = serial_driver; callout_driver.name = "cua"; callout_driver.major = TTYAUX_MAJOR; callout_driver.subtype = SERIAL_TYPE_CALLOUT; if (tty_register_driver(&serial_driver)) panic("Couldn't register serial driver\n"); if (tty_register_driver(&callout_driver)) panic("Couldn't register callout driver\n"); save_flags(flags); cli(); /* * Configure all the attached serial ports. */ for (i = 0, info = nios_soft; (i < NR_PORTS); i++, info++) { info->magic = SERIAL_MAGIC; info->tty = 0; info->custom_divisor = 16; info->close_delay = 50; info->closing_wait = 3000; info->x_char = 0; info->event = 0; info->count = 0; info->blocked_open = 0; info->tqueue.routine = do_softint; info->tqueue.data = info; info->tqueue_hangup.routine = do_serial_hangup; info->tqueue_hangup.data = info; info->callout_termios =callout_driver.init_termios; info->normal_termios = serial_driver.init_termios; init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); info->line = i; printk("%s%d (irq = %d) is a builtin NIOS UART\n", serial_driver.name, info->line, info->irq); // rs_setsignals(info, 0, 0); if (request_irq(info->irq, rs_interrupt, 0, "NIOS serial", info)) panic("Unable to attach NIOS serial interrupt\n"); } restore_flags(flags); return 0; }
static void console_write(struct console *co, const char *buf, unsigned int len) { static struct etrax_dma_descr descr; static struct etrax_dma_descr descr2; static char tmp_buf[MIN_SIZE]; static int tmp_size = 0; unsigned long flags; #ifdef CONFIG_ETRAX_DEBUG_PORT_NULL /* no debug printout at all */ return; #endif #ifdef CONFIG_SVINTO_SIM /* no use to simulate the serial debug output */ SIMCOUT(buf,len); return; #endif save_flags(flags); cli(); #ifdef CONFIG_ETRAX_KGDB /* kgdb needs to output debug info using the gdb protocol */ putDebugString(buf, len); restore_flags(flags); return; #endif /* To make this work together with the real serial port driver * we have to make sure that everything is flushed when we leave * here. The following steps are made to assure this: * 1. Wait until DMA stops, FIFO is empty and serial port pipeline empty. * 2. Write at least half the FIFO to trigger flush to serial port. * 3. Wait until DMA stops, FIFO is empty and serial port pipeline empty. */ /* Do we have enough characters to make the DMA/FIFO happy? */ if (tmp_size + len < MIN_SIZE) { int size = min((int)(MIN_SIZE - tmp_size),(int)len); memcpy(&tmp_buf[tmp_size], buf, size); tmp_size += size; len -= size; /* Pad with space if complete line */ if (tmp_buf[tmp_size-1] == '\n') { memset(&tmp_buf[tmp_size-1], ' ', MIN_SIZE - tmp_size); tmp_buf[MIN_SIZE - 1] = '\n'; tmp_size = MIN_SIZE; len = 0; } else { /* Wait for more characters */ restore_flags(flags); return; } } /* make sure the transmitter is enabled. * NOTE: this overrides any setting done in ttySx, to 8N1, no auto-CTS. * in the future, move the tr/rec_ctrl shadows from etrax100ser.c to * shadows.c and use it here as well... */ *DEBUG_TR_CTRL = 0x40; while(*DEBUG_OCMD & 7); /* Until DMA is not running */ while(*DEBUG_STATUS & 0x7f); /* wait until output FIFO is empty as well */ udelay(200); /* Wait for last two characters to leave the serial transmitter */ if (tmp_size) { descr.ctrl = len ? 0 : d_eop | d_wait | d_eol; descr.sw_len = tmp_size; descr.buf = virt_to_phys(tmp_buf); descr.next = virt_to_phys(&descr2); descr2.ctrl = d_eop | d_wait | d_eol; descr2.sw_len = len; descr2.buf = virt_to_phys((char*)buf); } else { descr.ctrl = d_eop | d_wait | d_eol; descr.sw_len = len; descr.buf = virt_to_phys((char*)buf); } *DEBUG_FIRST = virt_to_phys(&descr); /* write to R_DMAx_FIRST */ *DEBUG_OCMD = 1; /* dma command start -> R_DMAx_CMD */ /* wait until the output dma channel is ready again */ while(*DEBUG_OCMD & 7); while(*DEBUG_STATUS & 0x7f); udelay(200); tmp_size = 0; restore_flags(flags); }
/* * ------------------------------------------------------------ * rs_close() * * This routine is called when the serial port gets closed. First, we * wait for the last remaining data to be sent. Then, we unlink its * S structure from the interrupt chain if necessary, and we free * that IRQ if nothing is left in the chain. * ------------------------------------------------------------ */ static void rs_close(struct tty_struct *tty, struct file * filp) { struct NIOS_serial * info = (struct NIOS_serial *)tty->driver_data; unsigned long flags; np_uart * uart= (np_uart *)(info->port); if (!info || serial_paranoia_check(info, tty->device, "rs_close")) return; save_flags(flags); cli(); if (tty_hung_up_p(filp)) { restore_flags(flags); return; } if ((tty->count == 1) && (info->count != 1)) { /* * Uh, oh. tty->count is 1, which means that the tty * structure will be freed. Info->count should always * be one in these conditions. If it's greater than * one, we've got real problems, since it means the * serial port won't be shutdown. */ printk("rs_close: bad serial port count; tty->count is 1, " "info->count is %d\n", info->count); info->count = 1; } if (--info->count < 0) { printk("rs_close: bad serial port count for ttyS%d: %d\n", info->line, info->count); info->count = 0; } if (info->count) { restore_flags(flags); return; } info->flags |= S_CLOSING; /* * Save the termios structure, since this port may have * separate termios for callout and dialin. */ if (info->flags & S_NORMAL_ACTIVE) info->normal_termios = *tty->termios; if (info->flags & S_CALLOUT_ACTIVE) info->callout_termios = *tty->termios; /* * Now we wait for the transmit buffer to clear; and we notify * the line discipline to only process XON/XOFF characters. */ tty->closing = 1; if (info->closing_wait != S_CLOSING_WAIT_NONE) tty_wait_until_sent(tty, info->closing_wait); /* * At this point we stop accepting input. To do this, we * disable the receive line status interrupts, and tell the * interrupt driver to stop checking the data ready bit in the * line status register. */ uart->np_uartcontrol &= ~(np_uartcontrol_irrdy_mask); shutdown(info); if (tty->driver.flush_buffer) tty->driver.flush_buffer(tty); if (tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty); tty->closing = 0; info->event = 0; info->tty = 0; if (tty->ldisc.num != ldiscs[N_TTY].num) { if (tty->ldisc.close) (tty->ldisc.close)(tty); tty->ldisc = ldiscs[N_TTY]; tty->termios->c_line = N_TTY; if (tty->ldisc.open) (tty->ldisc.open)(tty); } if (info->blocked_open) { if (info->close_delay) { current->state = TASK_INTERRUPTIBLE; schedule_timeout(info->close_delay); } wake_up_interruptible(&info->open_wait); } info->flags &= ~(S_NORMAL_ACTIVE|S_CALLOUT_ACTIVE| S_CLOSING); wake_up_interruptible(&info->close_wait); restore_flags(flags); }
static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE; unsigned char msr; unsigned long flags; struct rtc_time wtime; switch (cmd) { case RTC_RD_TIME: /* Read the time/date from RTC */ { save_flags(flags); cli(); /* Ensure clock and real-time-mode-register are accessible */ msr = rtc->msr & 0xc0; rtc->msr = 0x40; do { wtime.tm_sec = BCD2BIN(rtc->bcd_sec); wtime.tm_min = BCD2BIN(rtc->bcd_min); wtime.tm_hour = BCD2BIN(rtc->bcd_hr); wtime.tm_mday = BCD2BIN(rtc->bcd_dom); wtime.tm_mon = BCD2BIN(rtc->bcd_mth)-1; wtime.tm_year = BCD2BIN(rtc->bcd_year); if (wtime.tm_year < 70) wtime.tm_year += 100; wtime.tm_wday = BCD2BIN(rtc->bcd_dow)-1; } while (wtime.tm_sec != BCD2BIN(rtc->bcd_sec)); rtc->msr = msr; restore_flags(flags); return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0; } case RTC_SET_TIME: /* Set the RTC */ { struct rtc_time rtc_tm; unsigned char mon, day, hrs, min, sec, leap_yr; unsigned int yrs; if (!capable(CAP_SYS_ADMIN)) return -EACCES; if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time))) return -EFAULT; yrs = rtc_tm.tm_year; if (yrs < 1900) yrs += 1900; mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */ day = rtc_tm.tm_mday; hrs = rtc_tm.tm_hour; min = rtc_tm.tm_min; sec = rtc_tm.tm_sec; leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400)); if ((mon > 12) || (mon < 1) || (day == 0)) return -EINVAL; if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr))) return -EINVAL; if ((hrs >= 24) || (min >= 60) || (sec >= 60)) return -EINVAL; if (yrs >= 2070) return -EINVAL; save_flags(flags); cli(); /* Ensure clock and real-time-mode-register are accessible */ msr = rtc->msr & 0xc0; rtc->msr = 0x40; rtc->t0cr_rtmr = yrs%4; rtc->bcd_tenms = 0; rtc->bcd_sec = BIN2BCD(sec); rtc->bcd_min = BIN2BCD(min); rtc->bcd_hr = BIN2BCD(hrs); rtc->bcd_dom = BIN2BCD(day); rtc->bcd_mth = BIN2BCD(mon); rtc->bcd_year = BIN2BCD(yrs%100); if (rtc_tm.tm_wday >= 0) rtc->bcd_dow = BIN2BCD(rtc_tm.tm_wday+1); rtc->t0cr_rtmr = yrs%4 | 0x08; rtc->msr = msr; restore_flags(flags); return 0; } default: return -EINVAL; } }
static int lcd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct lcd_display button_display; unsigned long address, a; int index; switch (cmd) { case LCD_On: udelay(150); BusyCheck(); LCDWriteInst(0x0F); break; case LCD_Off: udelay(150); BusyCheck(); LCDWriteInst(0x08); break; case LCD_Reset: udelay(150); LCDWriteInst(0x3F); udelay(150); LCDWriteInst(0x3F); udelay(150); LCDWriteInst(0x3F); udelay(150); LCDWriteInst(0x3F); udelay(150); LCDWriteInst(0x01); udelay(150); LCDWriteInst(0x06); break; case LCD_Clear: udelay(150); BusyCheck(); LCDWriteInst(0x01); break; case LCD_Cursor_Left: udelay(150); BusyCheck(); LCDWriteInst(0x10); break; case LCD_Cursor_Right: udelay(150); BusyCheck(); LCDWriteInst(0x14); break; case LCD_Cursor_Off: udelay(150); BusyCheck(); LCDWriteInst(0x0C); break; case LCD_Cursor_On: udelay(150); BusyCheck(); LCDWriteInst(0x0F); break; case LCD_Blink_Off: udelay(150); BusyCheck(); LCDWriteInst(0x0E); break; case LCD_Get_Cursor_Pos:{ struct lcd_display display; udelay(150); BusyCheck(); display.cursor_address = ( LCDReadInst ); display.cursor_address = ( display.cursor_address & 0x07F ); if(copy_to_user((struct lcd_display*)arg, &display, sizeof(struct lcd_display))) return -EFAULT; break; } case LCD_Set_Cursor_Pos: { struct lcd_display display; if(copy_from_user(&display, (struct lcd_display*)arg, sizeof(struct lcd_display))) return -EFAULT; a = (display.cursor_address | kLCD_Addr ); udelay(150); BusyCheck(); LCDWriteInst( a ); break; } case LCD_Get_Cursor: { struct lcd_display display; udelay(150); BusyCheck(); display.character = LCDReadData; if(copy_to_user((struct lcd_display*)arg, &display, sizeof(struct lcd_display))) return -EFAULT; udelay(150); BusyCheck(); LCDWriteInst(0x10); break; } case LCD_Set_Cursor:{ struct lcd_display display; if(copy_from_user(&display, (struct lcd_display*)arg, sizeof(struct lcd_display))) return -EFAULT; udelay(150); BusyCheck(); LCDWriteData( display.character ); udelay(150); BusyCheck(); LCDWriteInst(0x10); break; } case LCD_Disp_Left: udelay(150); BusyCheck(); LCDWriteInst(0x18); break; case LCD_Disp_Right: udelay(150); BusyCheck(); LCDWriteInst(0x1C); break; case LCD_Home: udelay(150); BusyCheck(); LCDWriteInst(0x02); break; case LCD_Write: { struct lcd_display display; if(copy_from_user(&display, (struct lcd_display*)arg, sizeof(struct lcd_display))) return -EFAULT; udelay(150); BusyCheck(); LCDWriteInst(0x80); udelay(150); BusyCheck(); for (index = 0; index < (display.size1); index++) { udelay(150); BusyCheck(); LCDWriteData( display.line1[index]); BusyCheck(); } udelay(150); BusyCheck(); LCDWriteInst(0xC0); udelay(150); BusyCheck(); for (index = 0; index < (display.size2); index++) { udelay(150); BusyCheck(); LCDWriteData( display.line2[index]); } break; } case LCD_Read: { struct lcd_display display; BusyCheck(); for (address = kDD_R00; address <= kDD_R01; address++) { a = (address | kLCD_Addr ); udelay(150); BusyCheck(); LCDWriteInst( a ); udelay(150); BusyCheck(); display.line1[address] = LCDReadData; } display.line1[ 0x27 ] = '\0'; for (address = kDD_R10; address <= kDD_R11; address++) { a = (address | kLCD_Addr ); udelay(150); BusyCheck(); LCDWriteInst( a ); udelay(150); BusyCheck(); display.line2[address - 0x40 ] = LCDReadData; } display.line2[ 0x27 ] = '\0'; if(copy_to_user((struct lcd_display*)arg, &display, sizeof(struct lcd_display))) return -EFAULT; break; } // set all GPIO leds to led_display.leds case LED_Set: { struct lcd_display led_display; if(copy_from_user(&led_display, (struct lcd_display*)arg, sizeof(struct lcd_display))) return -EFAULT; led_state = led_display.leds; LEDSet(led_state); break; } // set only bit led_display.leds case LED_Bit_Set: { int i; int bit=1; struct lcd_display led_display; if(copy_from_user(&led_display, (struct lcd_display*)arg, sizeof(struct lcd_display))) return -EFAULT; for (i=0;i<(int)led_display.leds;i++) { bit = 2*bit; } led_state = led_state | bit; LEDSet(led_state); break; } // clear only bit led_display.leds case LED_Bit_Clear: { int i; int bit=1; struct lcd_display led_display; if(copy_from_user(&led_display, (struct lcd_display*)arg, sizeof(struct lcd_display))) return -EFAULT; for (i=0;i<(int)led_display.leds;i++) { bit = 2*bit; } led_state = led_state & ~bit; LEDSet(led_state); break; } case BUTTON_Read: { button_display.buttons = GPIRead; if(copy_to_user((struct lcd_display*)arg, &button_display, sizeof(struct lcd_display))) return -EFAULT; break; } case LINK_Check: { button_display.buttons = *((volatile unsigned long *) (0xB0100060) ); if(copy_to_user((struct lcd_display*)arg, &button_display, sizeof(struct lcd_display))) return -EFAULT; break; } case LINK_Check_2: { int iface_num; /* panel-utils should pass in the desired interface status is wanted for * in "buttons" of the structure. We will set this to non-zero if the * link is in fact up for the requested interface. --DaveM */ if(copy_from_user(&button_display, (struct lcd_display *)arg, sizeof(button_display))) return -EFAULT; iface_num = button_display.buttons; #if defined(CONFIG_TULIP) && 0 if (iface_num >= 0 && iface_num < MAX_INTERFACES && linkcheck_callbacks[iface_num] != NULL) { button_display.buttons = linkcheck_callbacks[iface_num](linkcheck_cookies[iface_num]); } else #endif button_display.buttons = 0; if(__copy_to_user((struct lcd_display*)arg, &button_display, sizeof(struct lcd_display))) return -EFAULT; break; } // Erase the flash case FLASH_Erase: { int ctr=0; // Chip Erase Sequence WRITE_FLASH( kFlash_Addr1, kFlash_Data1 ); WRITE_FLASH( kFlash_Addr2, kFlash_Data2 ); WRITE_FLASH( kFlash_Addr1, kFlash_Erase3 ); WRITE_FLASH( kFlash_Addr1, kFlash_Data1 ); WRITE_FLASH( kFlash_Addr2, kFlash_Data2 ); WRITE_FLASH( kFlash_Addr1, kFlash_Erase6 ); printk( "Erasing Flash.\n"); while ( (!dqpoll(0x00000000,0xFF)) && (!timeout(0x00000000)) ) { ctr++; } printk("\n"); printk("\n"); printk("\n"); if (READ_FLASH(0x07FFF0)==0xFF) { printk("Erase Successful\r\n"); } else if (timeout) { printk("Erase Timed Out\r\n"); } break; } // burn the flash case FLASH_Burn: { volatile unsigned long burn_addr; unsigned long flags; int i; unsigned char *rom; struct lcd_display display; if(copy_from_user(&display, (struct lcd_display*)arg, sizeof(struct lcd_display))) return -EFAULT; rom = (unsigned char *) kmalloc((128),GFP_ATOMIC); if ( rom == NULL ) { printk ("broken\n"); return 1; } printk("Churning and Burning -"); save_flags(flags); for (i=0; i<FLASH_SIZE; i=i+128) { if(copy_from_user(rom, display.RomImage + i, 128)) return -EFAULT; burn_addr = kFlashBase + i; cli(); for ( index = 0; index < ( 128 ) ; index++ ) { WRITE_FLASH( kFlash_Addr1, kFlash_Data1 ); WRITE_FLASH( kFlash_Addr2, kFlash_Data2 ); WRITE_FLASH( kFlash_Addr1, kFlash_Prog ); *((volatile unsigned char *)burn_addr) = (volatile unsigned char) rom[index]; while ( (!dqpoll(burn_addr,(volatile unsigned char) rom[index])) && (!timeout(burn_addr)) ) { } burn_addr++; } restore_flags(flags); if ( *((volatile unsigned char *)(burn_addr-1)) == (volatile unsigned char) rom[index-1] ) { } else if (timeout) { printk("Program timed out\r\n"); } } kfree(rom); break; } // read the flash all at once case FLASH_Read: { unsigned char *user_bytes; volatile unsigned long read_addr; int i; user_bytes = &(((struct lcd_display *)arg)->RomImage[0]); if(!access_ok(VERIFY_WRITE, user_bytes, FLASH_SIZE)) return -EFAULT; printk("Reading Flash"); for (i=0; i<FLASH_SIZE; i++) { unsigned char tmp_byte; read_addr = kFlashBase + i; tmp_byte = *((volatile unsigned char *)read_addr); if(__put_user (tmp_byte, &user_bytes[i])) return -EFAULT; } break; } default: return 0; break; } return 0; }
static void nm256_write_block (struct nm256_info *card, char *buffer, u32 amt) { u32 ringsize = card->playbackBufferSize; u32 endstop; unsigned long flags; if (amt > (ringsize / 2)) { printk (KERN_ERR "NM256: Write request too large: %d\n", amt); amt = (ringsize / 2); } if (amt < NM256_PLAY_WMARK_SIZE) { printk (KERN_ERR "NM256: Write request too small: %d\n", amt); return; } card->curPlayPos %= ringsize; card->requested_amt = amt; save_flags (flags); cli (); if ((card->curPlayPos + amt) >= ringsize) { u32 rem = ringsize - card->curPlayPos; nm256_writeBuffer8 (card, buffer, 1, card->abuf1 + card->curPlayPos, rem); if (amt > rem) nm256_writeBuffer8 (card, buffer + rem, 1, card->abuf1, amt - rem); } else nm256_writeBuffer8 (card, buffer, 1, card->abuf1 + card->curPlayPos, amt); /* * Setup the start-n-stop-n-limit registers, and start that engine * goin'. * * Normally we just let it wrap around to avoid the click-click * action scene. */ if (! card->playing) { /* The PBUFFER_END register in this case points to one sample before the end of the buffer. */ int w = (card->dev_for_play == card->dev[0] ? 0 : 1); int sampsize = (card->sinfo[w].bits == 16 ? 2 : 1); if (card->sinfo[w].stereo) sampsize *= 2; /* Need to set the not-normally-changing-registers up. */ nm256_writePort32 (card, 2, NM_PBUFFER_START, card->abuf1 + card->curPlayPos); nm256_writePort32 (card, 2, NM_PBUFFER_END, card->abuf1 + ringsize - sampsize); nm256_writePort32 (card, 2, NM_PBUFFER_CURRP, card->abuf1 + card->curPlayPos); } endstop = (card->curPlayPos + amt - NM256_PLAY_WMARK_SIZE) % ringsize; nm256_writePort32 (card, 2, NM_PBUFFER_WMARK, card->abuf1 + endstop); if (! card->playing) startPlay (card); restore_flags (flags); }
int ax25_rt_ioctl(unsigned int cmd, void *arg) { unsigned long flags; ax25_route *s, *t, *ax25_rt; struct ax25_routes_struct route; struct ax25_route_opt_struct rt_option; ax25_dev *ax25_dev; int i; switch (cmd) { case SIOCADDRT: if (copy_from_user(&route, arg, sizeof(route))) return -EFAULT; if ((ax25_dev = ax25_addr_ax25dev(&route.port_addr)) == NULL) return -EINVAL; if (route.digi_count > AX25_MAX_DIGIS) return -EINVAL; for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next) { if (ax25cmp(&ax25_rt->callsign, &route.dest_addr) == 0 && ax25_rt->dev == ax25_dev->dev) { if (ax25_rt->digipeat != NULL) { kfree(ax25_rt->digipeat); ax25_rt->digipeat = NULL; } if (route.digi_count != 0) { if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) return -ENOMEM; ax25_rt->digipeat->lastrepeat = -1; ax25_rt->digipeat->ndigi = route.digi_count; for (i = 0; i < route.digi_count; i++) { ax25_rt->digipeat->repeated[i] = 0; ax25_rt->digipeat->calls[i] = route.digi_addr[i]; } } return 0; } } if ((ax25_rt = kmalloc(sizeof(ax25_route), GFP_ATOMIC)) == NULL) return -ENOMEM; ax25_rt->callsign = route.dest_addr; ax25_rt->dev = ax25_dev->dev; ax25_rt->digipeat = NULL; ax25_rt->ip_mode = ' '; if (route.digi_count != 0) { if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) { kfree(ax25_rt); return -ENOMEM; } ax25_rt->digipeat->lastrepeat = -1; ax25_rt->digipeat->ndigi = route.digi_count; for (i = 0; i < route.digi_count; i++) { ax25_rt->digipeat->repeated[i] = 0; ax25_rt->digipeat->calls[i] = route.digi_addr[i]; } } save_flags(flags); cli(); ax25_rt->next = ax25_route_list; ax25_route_list = ax25_rt; restore_flags(flags); break; case SIOCDELRT: if (copy_from_user(&route, arg, sizeof(route))) return -EFAULT; if ((ax25_dev = ax25_addr_ax25dev(&route.port_addr)) == NULL) return -EINVAL; ax25_rt = ax25_route_list; while (ax25_rt != NULL) { s = ax25_rt; ax25_rt = ax25_rt->next; if (s->dev == ax25_dev->dev && ax25cmp(&route.dest_addr, &s->callsign) == 0) { if (ax25_route_list == s) { ax25_route_list = s->next; if (s->digipeat != NULL) kfree(s->digipeat); kfree(s); } else { for (t = ax25_route_list; t != NULL; t = t->next) { if (t->next == s) { t->next = s->next; if (s->digipeat != NULL) kfree(s->digipeat); kfree(s); break; } } } } } break; case SIOCAX25OPTRT: if (copy_from_user(&rt_option, arg, sizeof(rt_option))) return -EFAULT; if ((ax25_dev = ax25_addr_ax25dev(&rt_option.port_addr)) == NULL) return -EINVAL; for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next) { if (ax25_rt->dev == ax25_dev->dev && ax25cmp(&rt_option.dest_addr, &ax25_rt->callsign) == 0) { switch (rt_option.cmd) { case AX25_SET_RT_IPMODE: switch (rt_option.arg) { case ' ': case 'D': case 'V': ax25_rt->ip_mode = rt_option.arg; break; default: return -EINVAL; } break; default: return -EINVAL; } } } break; default: return -EINVAL; } return 0; }
static void hfc_fill_fifo(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; long flags; int idx, fcnt; int count; u_char cip; char tmp[64]; if (!bcs->hw.hfc.tx_skb) return; if (bcs->hw.hfc.tx_skb->len <= 0) return; save_flags(flags); cli(); SelFiFo(cs, HFCB_SEND | HFCB_CHANNEL(bcs->channel)); cip = HFCB_FIFO | HFCB_F1 | HFCB_SEND | HFCB_CHANNEL(bcs->channel); WaitNoBusy(cs); bcs->hw.hfc.f1 = ReadReg(cs, HFCD_DATA, cip); WaitNoBusy(cs); cip = HFCB_FIFO | HFCB_F2 | HFCB_SEND | HFCB_CHANNEL(bcs->channel); WaitNoBusy(cs); bcs->hw.hfc.f2 = ReadReg(cs, HFCD_DATA, cip); bcs->hw.hfc.send[bcs->hw.hfc.f1] = ReadZReg(cs, HFCB_FIFO | HFCB_Z1 | HFCB_SEND | HFCB_CHANNEL(bcs->channel)); sti(); if (cs->debug & L1_DEB_HSCX) { sprintf(tmp, "hfc_fill_fifo %d f1(%d) f2(%d) z1(%x)", bcs->channel, bcs->hw.hfc.f1, bcs->hw.hfc.f2, bcs->hw.hfc.send[bcs->hw.hfc.f1]); debugl1(cs, tmp); } fcnt = bcs->hw.hfc.f1 - bcs->hw.hfc.f2; if (fcnt < 0) fcnt += 32; if (fcnt > 30) { if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfc_fill_fifo more as 30 frames"); restore_flags(flags); return; } count = GetFreeFifoBytes_B(bcs); if (cs->debug & L1_DEB_HSCX) { sprintf(tmp, "hfc_fill_fifo %d count(%d/%d),%lx", bcs->channel, bcs->hw.hfc.tx_skb->len, count, current->state); debugl1(cs, tmp); } if (count < bcs->hw.hfc.tx_skb->len) { if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfc_fill_fifo no fifo mem"); restore_flags(flags); return; } cip = HFCB_FIFO | HFCB_FIFO_IN | HFCB_SEND | HFCB_CHANNEL(bcs->channel); idx = 0; cli(); WaitForBusy(cs); WaitNoBusy(cs); WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->hw.hfc.tx_skb->data[idx++]); while (idx < bcs->hw.hfc.tx_skb->len) { cli(); if (!WaitNoBusy(cs)) break; WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->hw.hfc.tx_skb->data[idx]); sti(); idx++; } if (idx != bcs->hw.hfc.tx_skb->len) { sti(); debugl1(cs, "FIFO Send BUSY error"); printk(KERN_WARNING "HFC S FIFO channel %d BUSY Error\n", bcs->channel); } else { bcs->tx_cnt -= bcs->hw.hfc.tx_skb->len; if (bcs->st->lli.l1writewakeup && (PACKET_NOACK != bcs->hw.hfc.tx_skb->pkt_type)) bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hfc.tx_skb->len); dev_kfree_skb(bcs->hw.hfc.tx_skb); bcs->hw.hfc.tx_skb = NULL; } WaitForBusy(cs); cli(); WaitNoBusy(cs); ReadReg(cs, HFCD_DATA, HFCB_FIFO | HFCB_F1_INC | HFCB_SEND | HFCB_CHANNEL(bcs->channel)); sti(); WaitForBusy(cs); test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); restore_flags(flags); return; }
static int ibmlana_tx(struct sk_buff *skb, struct IBMLANA_NETDEV *dev) { ibmlana_priv *priv = (ibmlana_priv *) dev->priv; int retval = 0, tmplen, addr; unsigned long flags; tda_t tda; int baddr; /* if we get called with a NULL descriptor, the Ethernet layer thinks our card is stuck an we should reset it. We'll do this completely: */ if (skb == NULL) { printk("%s: Resetting SONIC\n", dev->name); StopSONIC(dev); InitBoard(dev); return 0; /* don't try to free the block here ;-) */ } /* find out if there are free slots for a frame to transmit. If not, the upper layer is in deep desperation and we simply ignore the frame. */ if (priv->txusedcnt >= TXBUFCNT) { retval = -EIO; priv->stat.tx_dropped++; goto tx_done; } /* copy the frame data into the next free transmit buffer - fillup missing */ tmplen = skb->len; if (tmplen < 60) tmplen = 60; baddr = priv->txbufstart + (priv->nexttxdescr * PKTSIZE); IBMLANA_TOIO(dev->mem_start + baddr, skb->data, skb->len); /* copy filler into RAM - in case we're filling up... we're filling a bit more than necessary, but that doesn't harm since the buffer is far larger... Sorry Linus for the filler string but I couldn't resist ;-) */ if (tmplen > skb->len) { char *fill = "NetBSD is a nice OS too! "; unsigned int destoffs = skb->len, l = strlen(fill); while (destoffs < tmplen) { IBMLANA_TOIO(dev->mem_start + baddr + destoffs, fill, l); destoffs += l; } } /* set up the new frame descriptor */ addr = priv->tdastart + (priv->nexttxdescr * sizeof(tda_t)); IBMLANA_FROMIO(&tda, dev->mem_start + addr, sizeof(tda_t)); tda.length = tda.fraglength = tmplen; IBMLANA_TOIO(dev->mem_start + addr, &tda, sizeof(tda_t)); /* if there were no active descriptors, trigger the SONIC */ save_flags(flags); cli(); priv->txusedcnt++; priv->txused[priv->nexttxdescr] = 1; /* are all transmission slots used up ? */ if (priv->txusedcnt >= TXBUFCNT) #if (LINUX_VERSION_CODE >= 0x02032a) netif_stop_queue(dev); #else dev->tbusy = 1; #endif if (priv->txusedcnt == 1) StartTx(dev, priv->nexttxdescr); priv->nexttxdescr = (priv->nexttxdescr + 1) % TXBUFCNT; restore_flags(flags); tx_done: /* When did that change exactly ? */ #if (LINUX_VERSION_CODE >= 0x20200) dev_kfree_skb(skb); #else dev_kfree_skb(skb, FREE_WRITE); #endif return retval; }