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

📄 pcl816.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
}/*============================================================================== Start/stop pacer onboard pacer*/static voidstart_pacer (comedi_device * dev, int mode, unsigned int divisor1,	     unsigned int divisor2){	outb (0x32, dev->iobase + PCL816_CTRCTL);	outb (0xff, dev->iobase + PCL816_CTR0);	outb (0x00, dev->iobase + PCL816_CTR0);	comedi_udelay (1);    outb(0xb4, dev->iobase + PCL816_CTRCTL);	// set counter 2 as mode 3    outb(0x74, dev->iobase + PCL816_CTRCTL);	// set counter 1 as mode 3    comedi_udelay(1);	if (mode == 1) {	    DPRINTK("mode %d, divisor1 %d, divisor2 %d\n", mode, divisor1, divisor2);		outb(divisor2 & 0xff, dev->iobase + PCL816_CTR2);		outb((divisor2 >> 8) & 0xff, dev->iobase + PCL816_CTR2);		outb(divisor1  & 0xff, dev->iobase + PCL816_CTR1);		outb((divisor1 >> 8) & 0xff, dev->iobase + PCL816_CTR1);    }		/* clear pending interrupts (just in case) *///	outb(0, dev->iobase + PCL816_CLRINT);}/*============================================================================== Check if channel list from user is builded correctly  If it's ok, then program scan/gain logic*/static intcheck_and_setup_channel_list (comedi_device * dev, comedi_subdevice * s, unsigned int *chanlist, int chanlen){  unsigned int chansegment[16];  unsigned int i, nowmustbechan, seglen, segpos;  // correct channel and range number check itself comedi/range.c   if (chanlen < 1) {      comedi_error (dev, "range/channel list is empty!");      return 0;  }  if (chanlen > 1)    {      chansegment[0] = chanlist[0];	// first channel is everytime ok      for (i = 1, seglen = 1; i < chanlen; i++, seglen++)	{		  		// build part of chanlist	  DEBUG(rt_printk("%d. %d %d\n",i,CR_CHAN(chanlist[i]),CR_RANGE(chanlist[i]));)	  if (chanlist[0] == chanlist[i])	    break;		// we detect loop, this must by finish	  nowmustbechan = (CR_CHAN (chansegment[i - 1]) + 1) % chanlen;	  if (nowmustbechan != CR_CHAN (chanlist[i])) {	  	// channel list isn't continous :-(	      rt_printk("comedi%d: pcl816: channel list must be continous! chanlist[%i]=%d but must be %d or %d!\n",		 dev->minor, i, CR_CHAN (chanlist[i]), nowmustbechan, CR_CHAN (chanlist[0]));	      return 0;       }	  chansegment[i] = chanlist[i];	// well, this is next correct channel in list	}    for (i = 0, segpos = 0; i < chanlen; i++)	{			// check whole chanlist	  DEBUG(rt_printk("%d %d=%d %d\n",CR_CHAN(chansegment[i%seglen]),CR_RANGE(chansegment[i%seglen]),CR_CHAN(chanlist[i]),CR_RANGE(chanlist[i]));)	  if (chanlist[i] != chansegment[i % seglen]) {	      rt_printk("comedi%d: pcl816: bad channel or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n",		 dev->minor, i, CR_CHAN (chansegment[i]),		 CR_RANGE (chansegment[i]), CR_AREF (chansegment[i]),		 CR_CHAN (chanlist[i % seglen]),		 CR_RANGE(chanlist[i % seglen]),		 CR_AREF (chansegment[i % seglen]));	      return 0;		// chan/gain list is strange	    }	}    }  else    {      seglen = 1;    }  devpriv->ai_act_chanlist_len = seglen;  devpriv->ai_act_chanlist_pos = 0;  for (i = 0; i < seglen; i++) {				// store range list to card      devpriv->ai_act_chanlist[i] = CR_CHAN (chanlist[i]);	  outb (CR_CHAN(chanlist[0]) & 0xf, dev->iobase + PCL816_MUX);		  outb (CR_RANGE(chanlist[0]), dev->iobase + PCL816_RANGE);	/* select gain */  }  comedi_udelay (1);  outb (devpriv->ai_act_chanlist[0] | (devpriv->ai_act_chanlist[seglen - 1] << 4),	dev->iobase + PCL816_MUX);	/* select channel interval to scan */  return 1;			// we can serve this with MUX logic}/* ==============================================================================  Enable(1)/disable(0) periodic interrupts from RTC*/static int set_rtc_irq_bit(unsigned char bit){        unsigned char val;        unsigned long flags;         if (bit==1) {		RTC_timer_lock++;		if (RTC_timer_lock>1) return 0;	} else {		RTC_timer_lock--;		if (RTC_timer_lock<0) RTC_timer_lock=0;		if (RTC_timer_lock>0) return 0;	}          save_flags(flags);        cli();        val = CMOS_READ(RTC_CONTROL);        if (bit) { val |= RTC_PIE; }    	    else { val &=  ~RTC_PIE; }        CMOS_WRITE(val, RTC_CONTROL);        CMOS_READ(RTC_INTR_FLAGS);        restore_flags(flags);        return 0;}/* ==============================================================================  Free any resources that we have claimed  */static voidfree_resources (comedi_device * dev){  //rt_printk("free_resource()\n");  if (dev->private)    {      pcl816_ai_cancel (dev, devpriv->sub_ai);      pcl816_reset (dev);      if (devpriv->dma)	free_dma (devpriv->dma);      if (devpriv->dmabuf[0])	free_pages (devpriv->dmabuf[0], devpriv->dmapages[0]);      if (devpriv->dmabuf[1])	free_pages (devpriv->dmabuf[1], devpriv->dmapages[1]);      if (devpriv->rtc_irq)	comedi_free_irq (devpriv->rtc_irq, dev);      if ((devpriv->dma_rtc) && (RTC_lock == 1))	{	  if (devpriv->rtc_iobase)	    release_region (devpriv->rtc_iobase, devpriv->rtc_iosize);	}    }  if (dev->irq)    free_irq (dev->irq, dev);  if (dev->iobase)    release_region (dev->iobase, this_board->io_range);  //rt_printk("free_resource() end\n");}/* ==============================================================================   Initialization */static intpcl816_attach (comedi_device * dev, comedi_devconfig * it){  int ret;  int iobase;  int irq, dma;  unsigned long pages;  //int i;  comedi_subdevice *s;  /* claim our I/O space */  iobase = it->options[0];  printk("comedi%d: pcl816:  board=%s, ioport=0x%03x", dev->minor,		this_board->name, iobase);		   if (check_region (iobase, this_board->io_range) < 0) {      rt_printk ("I/O port conflict\n");      return -EIO;  }  request_region (iobase, this_board->io_range, "pcl816");  dev->iobase = iobase;  if (pcl816_check (iobase)) {     rt_printk (", I cann't detect board. FAIL!\n");     return -EIO;  }  if ((ret = alloc_private (dev, sizeof (pcl816_private))) < 0)    return ret;			/* Can't alloc mem */  /* set up some name stuff */  dev->board_name = this_board->name;  /* grab our IRQ */  irq = 0;  if (this_board->IRQbits != 0) {	/* board support IRQ */		irq = it->options[1];      if (irq > 0)	{			/* we want to use IRQ */	  if (((1 << irq) & this_board->IRQbits) == 0)	    {	      rt_printk (", IRQ %d is out of allowed range, DISABLING IT", irq);	      irq = 0;		/* Bad IRQ */	    }	  else	    {	      if (comedi_request_irq(irq, interrupt_pcl816, 0, "pcl816", dev)) {			 rt_printk (", unable to allocate IRQ %d, DISABLING IT",irq);  			 irq = 0;	/* Can't use IRQ */			}	      else	{		  rt_printk (", irq=%d", irq);		}	    }	}    }  dev->irq = irq;  if (irq)    {      devpriv->irq_free = 1;    }				/* 1=we have allocated irq */  else    {      devpriv->irq_free = 0;    }  devpriv->irq_blocked = 0;	/* number of subdevice which use IRQ */  devpriv->int816_mode = 0;	/* mode of irq */  /* grab RTC for DMA operations */  devpriv->dma_rtc = 0;  if (it->options[2] > 0)    {				// we want to use DMA      if (RTC_lock == 0)	{	  if (check_region (RTC_PORT (0), RTC_IO_EXTENT) < 0)	    goto no_rtc;	  request_region (RTC_PORT (0), RTC_IO_EXTENT, "pcl816 (RTC)");	}      devpriv->rtc_iobase = RTC_PORT (0);      devpriv->rtc_iosize = RTC_IO_EXTENT;      RTC_lock++;#ifdef UNTESTED_CODE      if (!comedi_request_irq (RTC_IRQ, interrupt_pcl816_ai_mode13_dma_rtc,	   0, "pcl816 DMA (RTC)", dev))	{		  devpriv->dma_rtc = 1;		  devpriv->rtc_irq = RTC_IRQ;		  rt_printk (", dma_irq=%d", devpriv->rtc_irq);	  } else {		  RTC_lock--;		  if (RTC_lock == 0)	    	{		      if (devpriv->rtc_iobase)			release_region (devpriv->rtc_iobase, devpriv->rtc_iosize);		    }		  devpriv->rtc_iobase = 0;		  devpriv->rtc_iosize = 0;	  }#else	printk("pcl816: RTC code missing");#endif	      }no_rtc:  /* grab our DMA */  dma = 0;  devpriv->dma = dma;  if ((devpriv->irq_free == 0) && (devpriv->dma_rtc == 0))    goto no_dma;		/* if we haven't IRQ, we can't use DMA */    if (this_board->DMAbits != 0) {  /* board support DMA */      dma = it->options[2];      if (dma < 1)			goto no_dma;		/* DMA disabled */			      if (((1 << dma) & this_board->DMAbits) == 0)	{	  	rt_printk (", DMA is out of allowed range, FAIL!\n");		return -EINVAL;	/* Bad DMA */	  }      ret = request_dma (dma, "pcl816");      if (ret) {	  	rt_printk (", unable to allocate DMA %d, FAIL!\n", dma);	 	return -EBUSY;	/* DMA isn't free */	  }      	  devpriv->dma = dma;      rt_printk (", dma=%d", dma);      pages = 2;		/* we need 16KB */      devpriv->dmabuf[0] = __get_dma_pages (GFP_KERNEL, pages);      	  if (!devpriv->dmabuf[0])	{	  		rt_printk (", unable to allocate DMA buffer, FAIL!\n");	  		/* maybe experiment with try_to_free_pages() will help .... */	  		return -EBUSY;	/* no buffer :-( */	  }      devpriv->dmapages[0] = pages;      devpriv->hwdmaptr[0] = virt_to_bus ((void *) devpriv->dmabuf[0]);      devpriv->hwdmasize[0] = (1 << pages) * PAGE_SIZE;      //rt_printk("%d %d %ld, ",devpriv->dmapages[0],devpriv->hwdmasize[0],PAGE_SIZE);      if (devpriv->dma_rtc == 0)	{			// we must do duble buff :-(	  	devpriv->dmabuf[1] = __get_dma_pages (GFP_KERNEL, pages);	  	if (!devpriv->dmabuf[1]) {	      rt_printk (", unable to allocate DMA buffer, FAIL!\n");	      return -EBUSY;	    }	  devpriv->dmapages[1] = pages;	  devpriv->hwdmaptr[1] = virt_to_bus ((void *) devpriv->dmabuf[1]);	  devpriv->hwdmasize[1] = (1 << pages) * PAGE_SIZE;	}    }no_dma:/*  if (this_board->n_aochan > 0)    subdevs[1] = COMEDI_SUBD_AO;  if (this_board->n_dichan > 0)    subdevs[2] = COMEDI_SUBD_DI;  if (this_board->n_dochan > 0)    subdevs[3] = COMEDI_SUBD_DO;*/  if ((ret = alloc_subdevices (dev, 1)) < 0)    return ret;  s = dev->subdevices + 0;  if (this_board->n_aichan > 0){    s->type = COMEDI_SUBD_AI;    devpriv->sub_ai = s;    dev->read_subdev = s;    s->subdev_flags = SDF_READABLE;    s->n_chan = this_board->n_aichan;    s->subdev_flags |= SDF_DIFF;    //printk (", %dchans DIFF DAC - %d", s->n_chan, i);    s->maxdata = this_board->ai_maxdata;    s->len_chanlist = this_board->ai_chanlist;    s->range_table = this_board->ai_range_type;    s->cancel = pcl816_ai_cancel;    s->do_cmdtest = pcl816_ai_cmdtest;    s->do_cmd = pcl816_ai_cmd;    s->poll = pcl816_ai_poll;    s->insn_read = pcl816_ai_insn_read;  }else{    s->type = COMEDI_SUBD_UNUSED;  }#if 0	case COMEDI_SUBD_AO:	  s->subdev_flags = SDF_WRITABLE | SDF_GROUND;	  s->n_chan = this_board->n_aochan;	  s->maxdata = this_board->ao_maxdata;	  s->len_chanlist = this_board->ao_chanlist;	  s->range_table = this_board->ao_range_type;	  break;	case COMEDI_SUBD_DI:	  s->subdev_flags = SDF_READABLE;	  s->n_chan = this_board->n_dichan;	  s->maxdata = 1;	  s->len_chanlist = this_board->n_dichan;	  s->range_table = &range_digital;	  break;	case COMEDI_SUBD_DO:	  s->subdev_flags = SDF_WRITABLE;	  s->n_chan = this_board->n_dochan;	  s->maxdata = 1;	  s->len_chanlist = this_board->n_dochan;	  s->range_table = &range_digital;	  break;	}      s++;    }#endif  pcl816_reset (dev);  rt_printk ("\n");  return 0;}/*==============================================================================  Removes device */static intpcl816_detach (comedi_device * dev){  DEBUG(rt_printk("comedi%d: pcl816: remove\n", dev->minor);)  free_resources (dev);  if (devpriv->dma_rtc)    RTC_lock--;  return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -