コード例 #1
0
ファイル: comx-hw-locomx.c プロジェクト: wxlong/Test
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;
}
コード例 #2
0
ファイル: nm256_audio.c プロジェクト: hugh712/Jollen
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);
}
コード例 #3
0
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);
}
コード例 #4
0
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);
		}
コード例 #5
0
__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;
}
コード例 #6
0
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 */
コード例 #7
0
ファイル: isdnloop.c プロジェクト: nighthawk149/fvs318g-cfw
/*
 * 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);
}
コード例 #8
0
ファイル: ip_masq.c プロジェクト: rohsaini/mkunity
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;
}
コード例 #9
0
ファイル: ip_masq.c プロジェクト: rohsaini/mkunity
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;
}
コード例 #10
0
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;
}
コード例 #11
0
ファイル: fdc-io.c プロジェクト: FatSunHYS/OSCourseDesign
/*  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;
}
コード例 #12
0
ファイル: ataints.c プロジェクト: TitaniumBoy/lin
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;
}
コード例 #13
0
ファイル: ataints.c プロジェクト: TitaniumBoy/lin
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;
	}
}
コード例 #14
0
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);
}
コード例 #15
0
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 */
コード例 #16
0
ファイル: ip_masq.c プロジェクト: rohsaini/mkunity
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;
 }
コード例 #17
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 */
コード例 #18
0
ファイル: ip_masq.c プロジェクト: rohsaini/mkunity
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;
}
コード例 #19
0
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 */
コード例 #21
0
ファイル: isdnloop.c プロジェクト: nighthawk149/fvs318g-cfw
/*
 * 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;
}
コード例 #22
0
/* 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;
}
コード例 #23
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);
}
コード例 #24
0
/*
 * ------------------------------------------------------------
 * 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);
}
コード例 #25
0
ファイル: rtc.c プロジェクト: dduval/kernel-rhel3
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;
	}
}
コード例 #26
0
ファイル: lcd.c プロジェクト: iPodLinux/linux-2.6.7-ipod
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;

}
コード例 #27
0
ファイル: nm256_audio.c プロジェクト: hugh712/Jollen
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);
}
コード例 #28
0
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;
}
コード例 #29
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;
}
コード例 #30
0
ファイル: ibmlana.c プロジェクト: dmgerman/original
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;
}