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

📄 cb_pcimdda.c

📁 最新rtlinux内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		return -ENOMEM;	/* * If you can probe the device to determine what device in a series * it is, this is the place to do it.  Otherwise, dev->board_ptr * should already be initialized. */	 	if ( (err = probe(dev, it)) ) return err;	/* Output some info */	printk("comedi%d: %s: ",dev->minor, thisboard->name);/* * Initialize dev->board_name.  Note that we can use the "thisboard" * macro now, since we just initialized it in the last line. */		dev->board_name = thisboard->name;/* * Allocate the subdevice structures.  alloc_subdevice() is a * convenient macro defined in comedidev.h. */	if(alloc_subdevices(dev, 2)<0)		return -ENOMEM;	s = dev->subdevices+0;	/* analog output subdevice */	s->type = COMEDI_SUBD_AO;	s->subdev_flags = SDF_WRITABLE | SDF_READABLE;	s->n_chan = thisboard->ao_chans;	s->maxdata = figure_out_maxdata(thisboard->ao_bits);	/* this is hard-coded here */	if(dev->options[2]){		s->range_table = &range_bipolar10;	}else{		s->range_table = &range_bipolar5;	}	s->insn_write = &ao_winsn;	s->insn_read = &ao_rinsn;	s = dev->subdevices+1;	/* digital i/o subdevice */    if(thisboard->dio_chans) {        switch(thisboard->dio_method) {        case DIO_8255:           /* this is a straight 8255, so register us with the 8255 driver */            subdev_8255_init(dev, s, NULL,                               (unsigned long)(devpriv->dio_registers));            devpriv->attached_to_8255 = 1;            break;        case DIO_INTERNAL:        default:            printk("DIO_INTERNAL not implemented yet!\n");            return -ENXIO;            break;        }    } else {      s->type = COMEDI_SUBD_UNUSED;    }	    devpriv->attached_successfully = 1;    printk("attached\n");        return 1;}/* * _detach is called to deconfigure a device.  It should deallocate * resources.   * This function is also called when _attach() fails, so it should be * careful not to release resources that were not necessarily * allocated by _attach().  dev->private and dev->subdevices are * deallocated automatically by the core. */static int detach(comedi_device *dev){    if (devpriv) {        if (devpriv->registers && thisboard) {            release_region(devpriv->registers, REG_SZ);            devpriv->registers = 0;        }        if (dev->subdevices && devpriv->attached_to_8255) {            /* de-register us from the 8255 driver */            subdev_8255_cleanup(dev,dev->subdevices + 2);            devpriv->attached_to_8255 = 0;        }        if (devpriv->attached_successfully && thisboard)            printk("comedi%d: %s: detached\n", dev->minor, thisboard->name);    }		return 0;}static int ao_winsn(comedi_device *dev, comedi_subdevice *s, comedi_insn *insn,		    lsampl_t *data){   int i;   int chan = CR_CHAN(insn->chanspec);   int offset = devpriv->registers + chan*2;	/* Writing a list of values to an AO channel is probably not	 * very useful, but that's how the interface is defined. */   for(i=0;i<insn->n;i++) {       /*  first, load the low byte */        outb((char)(data[i] & 0x00ff), offset);       /*  next, write the high byte -- only after this is written is           the channel voltage updated in the DAC, unless           we're in simultaneous xfer mode (jumper on card)           then a rinsn is necessary to actually update the DAC --           see ao_rinsn() below... */       outb((char)(data[i]>>8 & 0x00ff), offset + 1);       /* for testing only.. the actual rinsn SHOULD do an inw!          (see the stuff about simultaneous XFER mode on this board) */       devpriv->ao_readback[chan] = data[i];   }   /* return the number of samples read/written */   return i;}/* AO subdevices should have a read insn as well as a write insn.   Usually this means copying a value stored in devpriv->ao_readback.    However, since this board has this jumper setting called "Simultaneous   Xfer mode" (off by default), we will support it.  Simultaneaous xfer   mode is accomplished by loading ALL the values you want for AO in all the    channels, then READing off one of the AO registers to initiate the    instantaneous simultaneous update of all DAC outputs, which makes   all AO channels update simultaneously.  This is useful for some control   applications, I would imagine.*/static int ao_rinsn(comedi_device *dev, comedi_subdevice *s, comedi_insn *insn,		    lsampl_t *data){    int i;    int chan = CR_CHAN(insn->chanspec);    for(i=0;i<insn->n;i++) {      inw(devpriv->registers + chan*2);      /* should I set data[i] to the result of the actual read on the register	 or the cached lsampl_t in devpriv->ao_readback[]? */      data[i] = devpriv->ao_readback[chan];    }    return i;}/*---------------------------------------------------------------------------  HELPER FUNCTION DEFINITIONS-----------------------------------------------------------------------------*//*  *  Probes for a supported device. * *  Prerequisite: private be allocated already inside dev *    *  If the device is found, it returns 0 and has the following side effects: * *  o  assigns a struct pci_dev * to dev->private->pci_dev  *  o  assigns a struct board * to dev->board_ptr *  o  sets dev->private->registers *  o  sets dev->private->dio_registers * *  Otherwise, returns a -errno on error */static int probe(comedi_device *dev, const comedi_devconfig *it) {    struct pci_dev *pcidev;	int index, registers;	pci_for_each_dev(pcidev)	{		// is it not a computer boards card?		if(pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS)			continue;		// loop through cards supported by this driver		for(index = 0; index < N_BOARDS; index++)		{			if(boards[index].device_id != pcidev->device)				continue;			// was a particular bus/slot requested?			if(it->options[0] || it->options[1])			{				// are we on the wrong bus/slot?				if(pcidev->bus->number != it->options[0] ||				   PCI_SLOT(pcidev->devfn) != it->options[1])				{					continue;				}			}			/* found ! */			/* todo: if we support more than 1 board, revise			   this to be more generic */            			devpriv->pci_dev = pcidev;			pci_enable_device(devpriv->pci_dev); /* make sure board is on */			dev->board_ptr = boards + index;			registers = pci_resource_start(devpriv->pci_dev, REGS_BADRINDEX);			request_region(registers, REG_SZ,thisboard->name);#if 0			{			  printk("cb_pcimdda: "				 "I/O port conflict failed to allocate ports "				 "0x%x to 0x%x\n", registers, 				 registers + REG_SZ - 1);			  return -EBUSY;			}#endif			devpriv->registers = registers;                        			devpriv->dio_registers 			  = devpriv->registers + thisboard->dio_offset;			return 0;		}	}    printk("cb_pcimdda: No supported ComputerBoards/MeasurementComputing "           "card found at the requested position\n");	return -ENODEV;}/* returns a maxdata value for a given n_bits */static inline lsampl_t figure_out_maxdata(int bits){    lsampl_t max = 0;    int i;    for (i = 0; i < bits; i++) {      max <<= 1;      max |=  1U;    }    return max;}

⌨️ 快捷键说明

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