RTXI 1.3
comedi/comedi/drivers/adl_pci9118.c
Go to the documentation of this file.
00001 /*
00002  *  comedi/drivers/adl_pci9118.c
00003  *
00004  *  hardware driver for ADLink cards:
00005  *   card:   PCI-9118DG, PCI-9118HG, PCI-9118HR
00006  *   driver: pci9118dg,  pci9118hg,  pci9118hr
00007  *
00008  * Author: Michal Dobes <dobes@tesnet.cz>
00009  *
00010 */
00011 /*
00012 Driver: adl_pci9118
00013 Description: Adlink PCI-9118DG, PCI-9118HG, PCI-9118HR
00014 Author: Michal Dobes <dobes@tesnet.cz>
00015 Devices: [ADLink] PCI-9118DG (pci9118dg), PCI-9118HG (pci9118hg),
00016   PCI-9118HR (pci9118hr)
00017 Status: works
00018 
00019 This driver supports AI, AO, DI and DO subdevices.
00020 AI subdevice supports cmd and insn interface,
00021 other subdevices support only insn interface.
00022 For AI:
00023 - If cmd->scan_begin_src=TRIG_EXT then trigger input is TGIN (pin 46).
00024 - If cmd->convert_src=TRIG_EXT then trigger input is EXTTRG (pin 44).
00025 - If cmd->start_src/stop_src=TRIG_EXT then trigger input is TGIN (pin 46).
00026 - It is not neccessary to have cmd.scan_end_arg=cmd.chanlist_len but
00027   cmd.scan_end_arg modulo cmd.chanlist_len must by 0.
00028 - If return value of cmdtest is 5 then you've bad channel list
00029   (it isn't possible mixture S.E. and DIFF inputs or bipolar and unipolar
00030   ranges).
00031 
00032 There are some hardware limitations:
00033 a) You cann't use mixture of unipolar/bipoar ranges or differencial/single
00034    ended inputs.
00035 b) DMA transfers must have the length aligned to two samples (32 bit),
00036    so there is some problems if cmd->chanlist_len is odd. This driver tries
00037    bypass this with adding one sample to the end of the every scan and discard
00038    it on output but this cann't be used if cmd->scan_begin_src=TRIG_FOLLOW
00039    and is used flag TRIG_WAKE_EOS, then driver switch to interrupt driven mode
00040    with interrupt after every sample.
00041 c) If isn't used DMA then you can use only mode where
00042    cmd->scan_begin_src=TRIG_FOLLOW.
00043 
00044 Configuration options:
00045   [0] - PCI bus of device (optional)
00046   [1] - PCI slot of device (optional)
00047           If bus/slot is not specified, then first available PCI
00048           card will be used.
00049   [2] - 0= standard 8 DIFF/16 SE channels configuration
00050         n= external multiplexer connected, 1<=n<=256
00051   [3] - 0=autoselect DMA or EOC interrupts operation
00052         1=disable DMA mode
00053         3=disable DMA and INT, only insn interface will work
00054   [4] - sample&hold signal - card can generate signal for external S&H board
00055         0=use SSHO (pin 45) signal is generated in onboard hardware S&H logic
00056         0!=use ADCHN7 (pin 23) signal is generated from driver, number
00057            say how long delay is requested in ns and sign polarity of the hold
00058            (in this case external multiplexor can serve only 128 channels)
00059   [5] - 0=stop measure on all hardware errors
00060         2|=ignore ADOR - A/D Overrun status
00061         8|=ignore Bover - A/D Burst Mode Overrun status
00062         256|=ignore nFull - A/D FIFO Full status
00063 
00064 */
00065 #include <linux/comedidev.h>
00066 
00067 #include <linux/delay.h>
00068 
00069 #include "amcc_s5933.h"
00070 #include "8253.h"
00071 #include "comedi_pci.h"
00072 #include "comedi_fc.h"
00073 
00074 /* paranoid checks are broken */
00075 #undef PCI9118_PARANOIDCHECK    /* if defined, then is used code which control correct channel number on every 12 bit sample */
00076 
00077 #undef PCI9118_EXTDEBUG         /* if defined then driver prints a lot of messages */
00078 
00079 #undef DPRINTK
00080 #ifdef PCI9118_EXTDEBUG
00081 #define DPRINTK(fmt, args...) rt_printk(fmt, ## args)
00082 #else
00083 #define DPRINTK(fmt, args...)
00084 #endif
00085 
00086 #define IORANGE_9118    64      /* I hope */
00087 #define PCI9118_CHANLEN 255     /* len of chanlist, some source say 256, but reality looks like 255 :-( */
00088 
00089 #define PCI9118_CNT0    0x00    /* R/W: 8254 couter 0 */
00090 #define PCI9118_CNT1    0x04    /* R/W: 8254 couter 0 */
00091 #define PCI9118_CNT2    0x08    /* R/W: 8254 couter 0 */
00092 #define PCI9118_CNTCTRL 0x0c    /* W:   8254 counter control */
00093 #define PCI9118_AD_DATA 0x10    /* R:   A/D data */
00094 #define PCI9118_DA1     0x10    /* W:   D/A registers */
00095 #define PCI9118_DA2     0x14
00096 #define PCI9118_ADSTAT  0x18    /* R:   A/D status register */
00097 #define PCI9118_ADCNTRL 0x18    /* W:   A/D control register */
00098 #define PCI9118_DI      0x1c    /* R:   digi input register */
00099 #define PCI9118_DO      0x1c    /* W:   digi output register */
00100 #define PCI9118_SOFTTRG 0x20    /* W:   soft trigger for A/D */
00101 #define PCI9118_GAIN    0x24    /* W:   A/D gain/channel register */
00102 #define PCI9118_BURST   0x28    /* W:   A/D burst number register */
00103 #define PCI9118_SCANMOD 0x2c    /* W:   A/D auto scan mode */
00104 #define PCI9118_ADFUNC  0x30    /* W:   A/D function register */
00105 #define PCI9118_DELFIFO 0x34    /* W:   A/D data FIFO reset */
00106 #define PCI9118_INTSRC  0x38    /* R:   interrupt reason register */
00107 #define PCI9118_INTCTRL 0x38    /* W:   interrupt control register */
00108 
00109 // bits from A/D control register (PCI9118_ADCNTRL)
00110 #define AdControl_UniP  0x80    /* 1=bipolar, 0=unipolar */
00111 #define AdControl_Diff  0x40    /* 1=differential, 0= single end inputs */
00112 #define AdControl_SoftG 0x20    /* 1=8254 counter works, 0=counter stops */
00113 #define AdControl_ExtG  0x10    /* 1=8254 countrol controlled by TGIN(pin 46), 0=controled by SoftG */
00114 #define AdControl_ExtM  0x08    /* 1=external hardware trigger (pin 44), 0=internal trigger */
00115 #define AdControl_TmrTr 0x04    /* 1=8254 is iternal trigger source, 0=software trigger is source (register PCI9118_SOFTTRG) */
00116 #define AdControl_Int   0x02    /* 1=enable INT, 0=disable */
00117 #define AdControl_Dma   0x01    /* 1=enable DMA, 0=disable */
00118 
00119 // bits from A/D function register (PCI9118_ADFUNC)
00120 #define AdFunction_PDTrg        0x80    /* 1=positive, 0=negative digital trigger (only positive is correct) */
00121 #define AdFunction_PETrg        0x40    /* 1=positive, 0=negative external trigger (only positive is correct) */
00122 #define AdFunction_BSSH         0x20    /* 1=with sample&hold, 0=without */
00123 #define AdFunction_BM           0x10    /* 1=burst mode, 0=normal mode */
00124 #define AdFunction_BS           0x08    /* 1=burst mode start, 0=burst mode stop */
00125 #define AdFunction_PM           0x04    /* 1=post trigger mode, 0=not post trigger */
00126 #define AdFunction_AM           0x02    /* 1=about trigger mode, 0=not about trigger */
00127 #define AdFunction_Start        0x01    /* 1=trigger start, 0=trigger stop */
00128 
00129 // bits from A/D status register (PCI9118_ADSTAT)
00130 #define AdStatus_nFull  0x100   /* 0=FIFO full (fatal), 1=not full */
00131 #define AdStatus_nHfull 0x080   /* 0=FIFO half full, 1=FIFO not half full */
00132 #define AdStatus_nEpty  0x040   /* 0=FIFO empty, 1=FIFO not empty */
00133 #define AdStatus_Acmp   0x020   /*  */
00134 #define AdStatus_DTH    0x010   /* 1=external digital trigger */
00135 #define AdStatus_Bover  0x008   /* 1=burst mode overrun (fatal) */
00136 #define AdStatus_ADOS   0x004   /* 1=A/D over speed (warning) */
00137 #define AdStatus_ADOR   0x002   /* 1=A/D overrun (fatal) */
00138 #define AdStatus_ADrdy  0x001   /* 1=A/D already ready, 0=not ready */
00139 
00140 // bits for interrupt reason and control (PCI9118_INTSRC, PCI9118_INTCTRL)
00141 // 1=interrupt occur, enable source,  0=interrupt not occur, disable source
00142 #define Int_Timer       0x08    /* timer interrupt */
00143 #define Int_About       0x04    /* about trigger complete */
00144 #define Int_Hfull       0x02    /* A/D FIFO hlaf full */
00145 #define Int_DTrg        0x01    /* external digital trigger */
00146 
00147 #define START_AI_EXT    0x01    /* start measure on external trigger */
00148 #define STOP_AI_EXT     0x02    /* stop measure on external trigger */
00149 #define START_AI_INT    0x04    /* start measure on internal trigger */
00150 #define STOP_AI_INT     0x08    /* stop measure on internal trigger */
00151 
00152 #define EXTTRG_AI       0       /* ext trg is used by AI */
00153 
00154 static const comedi_lrange range_pci9118dg_hr = { 8, {
00155                         BIP_RANGE(5),
00156                         BIP_RANGE(2.5),
00157                         BIP_RANGE(1.25),
00158                         BIP_RANGE(0.625),
00159                         UNI_RANGE(10),
00160                         UNI_RANGE(5),
00161                         UNI_RANGE(2.5),
00162                         UNI_RANGE(1.25)
00163         }
00164 };
00165 
00166 static const comedi_lrange range_pci9118hg = { 8, {
00167                         BIP_RANGE(5),
00168                         BIP_RANGE(0.5),
00169                         BIP_RANGE(0.05),
00170                         BIP_RANGE(0.005),
00171                         UNI_RANGE(10),
00172                         UNI_RANGE(1),
00173                         UNI_RANGE(0.1),
00174                         UNI_RANGE(0.01)
00175         }
00176 };
00177 
00178 #define PCI9118_BIPOLAR_RANGES  4       /* used for test on mixture of BIP/UNI ranges */
00179 
00180 static int pci9118_attach(comedi_device * dev, comedi_devconfig * it);
00181 static int pci9118_detach(comedi_device * dev);
00182 
00183 typedef struct {
00184         const char *name;       // board name
00185         int vendor_id;          // PCI vendor a device ID of card
00186         int device_id;
00187         int iorange_amcc;       // iorange for own S5933 region
00188         int iorange_9118;       // pass thru card region size
00189         int n_aichan;           // num of A/D chans
00190         int n_aichand;          // num of A/D chans in diff mode
00191         int mux_aichan;         // num of A/D chans with external multiplexor
00192         int n_aichanlist;       // len of chanlist
00193         int n_aochan;           // num of D/A chans
00194         int ai_maxdata;         // resolution of A/D
00195         int ao_maxdata;         // resolution of D/A
00196         const comedi_lrange *rangelist_ai;      // rangelist for A/D
00197         const comedi_lrange *rangelist_ao;      // rangelist for D/A
00198         unsigned int ai_ns_min; // max sample speed of card v ns
00199         unsigned int ai_pacer_min;      // minimal pacer value (c1*c2 or c1 in burst)
00200         int half_fifo_size;     // size of FIFO/2
00201 
00202 } boardtype;
00203 
00204 static DEFINE_PCI_DEVICE_TABLE(pci9118_pci_table) = {
00205         {PCI_VENDOR_ID_AMCC, 0x80d9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
00206         {0}
00207 };
00208 
00209 MODULE_DEVICE_TABLE(pci, pci9118_pci_table);
00210 
00211 static const boardtype boardtypes[] = {
00212         {"pci9118dg", PCI_VENDOR_ID_AMCC, 0x80d9,
00213                         AMCC_OP_REG_SIZE, IORANGE_9118,
00214                         16, 8, 256, PCI9118_CHANLEN, 2, 0x0fff, 0x0fff,
00215                         &range_pci9118dg_hr, &range_bipolar10,
00216                 3000, 12, 512},
00217         {"pci9118hg", PCI_VENDOR_ID_AMCC, 0x80d9,
00218                         AMCC_OP_REG_SIZE, IORANGE_9118,
00219                         16, 8, 256, PCI9118_CHANLEN, 2, 0x0fff, 0x0fff,
00220                         &range_pci9118hg, &range_bipolar10,
00221                 3000, 12, 512},
00222         {"pci9118hr", PCI_VENDOR_ID_AMCC, 0x80d9,
00223                         AMCC_OP_REG_SIZE, IORANGE_9118,
00224                         16, 8, 256, PCI9118_CHANLEN, 2, 0xffff, 0x0fff,
00225                         &range_pci9118dg_hr, &range_bipolar10,
00226                 10000, 40, 512},
00227 };
00228 
00229 #define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
00230 
00231 static comedi_driver driver_pci9118 = {
00232       driver_name:"adl_pci9118",
00233       module:THIS_MODULE,
00234       attach:pci9118_attach,
00235       detach:pci9118_detach,
00236       num_names:n_boardtypes,
00237       board_name:&boardtypes[0].name,
00238       offset:sizeof(boardtype),
00239 };
00240 
00241 COMEDI_PCI_INITCLEANUP(driver_pci9118, pci9118_pci_table);
00242 
00243 typedef struct {
00244         unsigned long iobase_a; // base+size for AMCC chip
00245         unsigned int master;    // master capable
00246         struct pci_dev *pcidev; // ptr to actual pcidev
00247         unsigned int usemux;    // we want to use external multiplexor!
00248 #ifdef PCI9118_PARANOIDCHECK
00249         unsigned short chanlist[PCI9118_CHANLEN + 1];   // list of scaned channel
00250         unsigned char chanlistlen;      // number of scanlist
00251 #endif
00252         unsigned char AdControlReg;     // A/D control register
00253         unsigned char IntControlReg;    // Interrupt control register
00254         unsigned char AdFunctionReg;    // A/D function register
00255         char valid;             // driver is ok
00256         char ai_neverending;    // we do unlimited AI
00257         unsigned int i8254_osc_base;    // frequence of onboard oscilator
00258         unsigned int ai_do;     // what do AI? 0=nothing, 1 to 4 mode
00259         unsigned int ai_act_scan;       // how many scans we finished
00260         unsigned int ai_buf_ptr;        // data buffer ptr in samples
00261         unsigned int ai_n_chan; // how many channels is measured
00262         unsigned int ai_n_scanlen;      // len of actual scanlist
00263         unsigned int ai_n_realscanlen;  // what we must transfer for one outgoing scan include front/back adds
00264         unsigned int ai_act_dmapos;     // position in actual real stream
00265         unsigned int ai_add_front;      // how many channels we must add before scan to satisfy S&H?
00266         unsigned int ai_add_back;       // how many channels we must add before scan to satisfy DMA?
00267         unsigned int *ai_chanlist;      // actaul chanlist
00268         unsigned int ai_timer1;
00269         unsigned int ai_timer2;
00270         unsigned int ai_flags;
00271         char ai12_startstop;    // measure can start/stop on external trigger
00272         unsigned int ai_divisor1, ai_divisor2;  // divisors for start of measure on external start
00273         unsigned int ai_data_len;
00274         sampl_t *ai_data;
00275         sampl_t ao_data[2];     // data output buffer
00276         unsigned int ai_scans;  // number of scans to do
00277         char dma_doublebuf;     // we can use double buffring
00278         unsigned int dma_actbuf;        // which buffer is used now
00279         sampl_t *dmabuf_virt[2];        // pointers to begin of DMA buffer
00280         unsigned long dmabuf_hw[2];     // hw address of DMA buff
00281         unsigned int dmabuf_size[2];    // size of dma buffer in bytes
00282         unsigned int dmabuf_use_size[2];        // which size we may now used for transfer
00283         unsigned int dmabuf_used_size[2];       // which size was trully used
00284         unsigned int dmabuf_panic_size[2];
00285         unsigned int dmabuf_samples[2]; // size in samples
00286         int dmabuf_pages[2];    // number of pages in buffer
00287         unsigned char cnt0_users;       // bit field of 8254 CNT0 users (0-unused, 1-AO, 2-DI, 3-DO)
00288         unsigned char exttrg_users;     // bit field of external trigger users (0-AI, 1-AO, 2-DI, 3-DO)
00289         unsigned int cnt0_divisor;      // actual CNT0 divisor
00290         void (*int_ai_func) (comedi_device *, comedi_subdevice *, unsigned short, unsigned int, unsigned short);        // ptr to actual interrupt AI function
00291         unsigned char ai16bits; // =1 16 bit card
00292         unsigned char usedma;   // =1 use DMA transfer and not INT
00293         unsigned char useeoshandle;     // =1 change WAKE_EOS DMA transfer to fit on every second
00294         unsigned char usessh;   // =1 turn on S&H support
00295         int softsshdelay;       // >0 use software S&H, numer is requested delay in ns
00296         unsigned char softsshsample;    // polarity of S&H signal in sample state
00297         unsigned char softsshhold;      // polarity of S&H signal in hold state
00298         unsigned int ai_maskerr;        // which warning was printed
00299         unsigned int ai_maskharderr;    // on which error bits stops
00300         unsigned int ai_inttrig_start;  // TRIG_INT for start
00301 } pci9118_private;
00302 
00303 #define devpriv ((pci9118_private *)dev->private)
00304 #define this_board ((boardtype *)dev->board_ptr)
00305 
00306 /*
00307 ==============================================================================
00308 */
00309 
00310 static int check_channel_list(comedi_device * dev, comedi_subdevice * s,
00311         int n_chan, unsigned int *chanlist, int frontadd, int backadd);
00312 static int setup_channel_list(comedi_device * dev, comedi_subdevice * s,
00313         int n_chan, unsigned int *chanlist, int rot, int frontadd, int backadd,
00314         int usedma, char eoshandle);
00315 static void start_pacer(comedi_device * dev, int mode, unsigned int divisor1,
00316         unsigned int divisor2);
00317 static int pci9118_reset(comedi_device * dev);
00318 static int pci9118_exttrg_add(comedi_device * dev, unsigned char source);
00319 static int pci9118_exttrg_del(comedi_device * dev, unsigned char source);
00320 static int pci9118_ai_cancel(comedi_device * dev, comedi_subdevice * s);
00321 static void pci9118_calc_divisors(char mode, comedi_device * dev,
00322         comedi_subdevice * s, unsigned int *tim1, unsigned int *tim2,
00323         unsigned int flags, int chans, unsigned int *div1, unsigned int *div2,
00324         char usessh, unsigned int chnsshfront);
00325 
00326 /*
00327 ==============================================================================
00328 */
00329 static int pci9118_insn_read_ai(comedi_device * dev, comedi_subdevice * s,
00330         comedi_insn * insn, lsampl_t * data)
00331 {
00332 
00333         int n, timeout;
00334 
00335         devpriv->AdControlReg = AdControl_Int & 0xff;
00336         devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
00337         outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);     // positive triggers, no S&H, no burst, burst stop, no post trigger, no about trigger, trigger stop
00338 
00339         if (!setup_channel_list(dev, s, 1, &insn->chanspec, 0, 0, 0, 0, 0))
00340                 return -EINVAL;
00341 
00342         outl(0, dev->iobase + PCI9118_DELFIFO); // flush FIFO
00343 
00344         for (n = 0; n < insn->n; n++) {
00345                 outw(0, dev->iobase + PCI9118_SOFTTRG); /* start conversion */
00346                 comedi_udelay(2);
00347                 timeout = 100;
00348                 while (timeout--) {
00349                         if (inl(dev->iobase + PCI9118_ADSTAT) & AdStatus_ADrdy)
00350                                 goto conv_finish;
00351                         comedi_udelay(1);
00352                 }
00353 
00354                 comedi_error(dev, "A/D insn timeout");
00355                 data[n] = 0;
00356                 outl(0, dev->iobase + PCI9118_DELFIFO); // flush FIFO
00357                 return -ETIME;
00358 
00359               conv_finish:
00360                 if (devpriv->ai16bits) {
00361                         data[n] =
00362                                 (inl(dev->iobase +
00363                                         PCI9118_AD_DATA) & 0xffff) ^ 0x8000;
00364                 } else {
00365                         data[n] =
00366                                 (inw(dev->iobase +
00367                                         PCI9118_AD_DATA) >> 4) & 0xfff;
00368                 }
00369         }
00370 
00371         outl(0, dev->iobase + PCI9118_DELFIFO); // flush FIFO
00372         return n;
00373 
00374 }
00375 
00376 /*
00377 ==============================================================================
00378 */
00379 static int pci9118_insn_write_ao(comedi_device * dev, comedi_subdevice * s,
00380         comedi_insn * insn, lsampl_t * data)
00381 {
00382         int n, chanreg, ch;
00383 
00384         ch = CR_CHAN(insn->chanspec);
00385         if (ch) {
00386                 chanreg = PCI9118_DA2;
00387         } else {
00388                 chanreg = PCI9118_DA1;
00389         }
00390 
00391         for (n = 0; n < insn->n; n++) {
00392                 outl(data[n], dev->iobase + chanreg);
00393                 devpriv->ao_data[ch] = data[n];
00394         }
00395 
00396         return n;
00397 }
00398 
00399 /*
00400 ==============================================================================
00401 */
00402 static int pci9118_insn_read_ao(comedi_device * dev, comedi_subdevice * s,
00403         comedi_insn * insn, lsampl_t * data)
00404 {
00405         int n, chan;
00406 
00407         chan = CR_CHAN(insn->chanspec);
00408         for (n = 0; n < insn->n; n++)
00409                 data[n] = devpriv->ao_data[chan];
00410 
00411         return n;
00412 }
00413 
00414 /*
00415 ==============================================================================
00416 */
00417 static int pci9118_insn_bits_di(comedi_device * dev, comedi_subdevice * s,
00418         comedi_insn * insn, lsampl_t * data)
00419 {
00420         data[1] = inl(dev->iobase + PCI9118_DI) & 0xf;
00421 
00422         return 2;
00423 }
00424 
00425 /*
00426 ==============================================================================
00427 */
00428 static int pci9118_insn_bits_do(comedi_device * dev, comedi_subdevice * s,
00429         comedi_insn * insn, lsampl_t * data)
00430 {
00431         if (data[0]) {
00432                 s->state &= ~data[0];
00433                 s->state |= (data[0] & data[1]);
00434                 outl(s->state & 0x0f, dev->iobase + PCI9118_DO);
00435         }
00436         data[1] = s->state;
00437 
00438         return 2;
00439 }
00440 
00441 /*
00442 ==============================================================================
00443 */
00444 static void interrupt_pci9118_ai_mode4_switch(comedi_device * dev)
00445 {
00446         devpriv->AdFunctionReg =
00447                 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_AM;
00448         outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
00449         outl(0x30, dev->iobase + PCI9118_CNTCTRL);
00450         outl((devpriv->dmabuf_hw[1 - devpriv->dma_actbuf] >> 1) & 0xff,
00451                 dev->iobase + PCI9118_CNT0);
00452         outl((devpriv->dmabuf_hw[1 - devpriv->dma_actbuf] >> 9) & 0xff,
00453                 dev->iobase + PCI9118_CNT0);
00454         devpriv->AdFunctionReg |= AdFunction_Start;
00455         outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
00456 }
00457 
00458 static unsigned int defragment_dma_buffer(comedi_device * dev,
00459         comedi_subdevice * s, sampl_t * dma_buffer, unsigned int num_samples)
00460 {
00461         unsigned int i = 0, j = 0;
00462         unsigned int start_pos = devpriv->ai_add_front,
00463                 stop_pos = devpriv->ai_add_front + devpriv->ai_n_chan;
00464         unsigned int raw_scanlen = devpriv->ai_add_front + devpriv->ai_n_chan +
00465                 devpriv->ai_add_back;
00466 
00467         for (i = 0; i < num_samples; i++) {
00468                 if (devpriv->ai_act_dmapos >= start_pos &&
00469                         devpriv->ai_act_dmapos < stop_pos) {
00470                         dma_buffer[j++] = dma_buffer[i];
00471                 }
00472                 devpriv->ai_act_dmapos++;
00473                 devpriv->ai_act_dmapos %= raw_scanlen;
00474         }
00475 
00476         return j;
00477 }
00478 
00479 /*
00480 ==============================================================================
00481 */
00482 static unsigned int move_block_from_dma(comedi_device * dev,
00483         comedi_subdevice * s, sampl_t * dma_buffer, unsigned int num_samples)
00484 {
00485         unsigned int num_bytes;
00486 
00487         num_samples = defragment_dma_buffer(dev, s, dma_buffer, num_samples);
00488         devpriv->ai_act_scan +=
00489                 (s->async->cur_chan + num_samples) / devpriv->ai_n_scanlen;
00490         s->async->cur_chan += num_samples;
00491         s->async->cur_chan %= devpriv->ai_n_scanlen;
00492         num_bytes =
00493                 cfc_write_array_to_buffer(s, dma_buffer,
00494                 num_samples * sizeof(sampl_t));
00495         if (num_bytes < num_samples * sizeof(sampl_t))
00496                 return -1;
00497         return 0;
00498 }
00499 
00500 /*
00501 ==============================================================================
00502 */
00503 static char pci9118_decode_error_status(comedi_device * dev,
00504         comedi_subdevice * s, unsigned char m)
00505 {
00506         if (m & 0x100) {
00507                 comedi_error(dev, "A/D FIFO Full status (Fatal Error!)");
00508                 devpriv->ai_maskerr &= ~0x100L;
00509         }
00510         if (m & 0x008) {
00511                 comedi_error(dev,
00512                         "A/D Burst Mode Overrun Status (Fatal Error!)");
00513                 devpriv->ai_maskerr &= ~0x008L;
00514         }
00515         if (m & 0x004) {
00516                 comedi_error(dev, "A/D Over Speed Status (Warning!)");
00517                 devpriv->ai_maskerr &= ~0x004L;
00518         }
00519         if (m & 0x002) {
00520                 comedi_error(dev, "A/D Overrun Status (Fatal Error!)");
00521                 devpriv->ai_maskerr &= ~0x002L;
00522         }
00523         if (m & devpriv->ai_maskharderr) {
00524                 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
00525                 pci9118_ai_cancel(dev, s);
00526                 comedi_event(dev, s);
00527                 return 1;
00528         }
00529 
00530         return 0;
00531 }
00532 
00533 static void pci9118_ai_munge(comedi_device * dev, comedi_subdevice * s,
00534         void *data, unsigned int num_bytes, unsigned int start_chan_index)
00535 {
00536         unsigned int i, num_samples = num_bytes / sizeof(sampl_t);
00537         sampl_t *array = data;
00538 
00539         for (i = 0; i < num_samples; i++) {
00540                 if (devpriv->usedma)
00541                         array[i] = be16_to_cpu(array[i]);
00542                 if (devpriv->ai16bits) {
00543                         array[i] ^= 0x8000;
00544                 } else {
00545                         array[i] = (array[i] >> 4) & 0x0fff;
00546                 }
00547         }
00548 }
00549 
00550 /*
00551 ==============================================================================
00552 */
00553 static void interrupt_pci9118_ai_onesample(comedi_device * dev,
00554         comedi_subdevice * s, unsigned short int_adstat, unsigned int int_amcc,
00555         unsigned short int_daq)
00556 {
00557         register sampl_t sampl;
00558 
00559         s->async->events = 0;
00560 
00561         if (int_adstat & devpriv->ai_maskerr)
00562                 if (pci9118_decode_error_status(dev, s, int_adstat))
00563                         return;
00564 
00565         sampl = inw(dev->iobase + PCI9118_AD_DATA);
00566 
00567 #ifdef PCI9118_PARANOIDCHECK
00568         if (devpriv->ai16bits == 0) {
00569                 if ((sampl & 0x000f) != devpriv->chanlist[s->async->cur_chan]) {        // data dropout!
00570                         rt_printk
00571                                 ("comedi: A/D  SAMPL - data dropout: received channel %d, expected %d!\n",
00572                                 sampl & 0x000f,
00573                                 devpriv->chanlist[s->async->cur_chan]);
00574                         s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
00575                         pci9118_ai_cancel(dev, s);
00576                         comedi_event(dev, s);
00577                         return;
00578                 }
00579         }
00580 #endif
00581         cfc_write_to_buffer(s, sampl);
00582         s->async->cur_chan++;
00583         if (s->async->cur_chan >= devpriv->ai_n_scanlen) {      /* one scan done */
00584                 s->async->cur_chan %= devpriv->ai_n_scanlen;
00585                 devpriv->ai_act_scan++;
00586                 if (!(devpriv->ai_neverending))
00587                         if (devpriv->ai_act_scan >= devpriv->ai_scans) {        /* all data sampled */
00588                                 pci9118_ai_cancel(dev, s);
00589                                 s->async->events |= COMEDI_CB_EOA;
00590                         }
00591         }
00592 
00593         if (s->async->events)
00594                 comedi_event(dev, s);
00595 }
00596 
00597 /*
00598 ==============================================================================
00599 */
00600 static void interrupt_pci9118_ai_dma(comedi_device * dev, comedi_subdevice * s,
00601         unsigned short int_adstat, unsigned int int_amcc,
00602         unsigned short int_daq)
00603 {
00604         unsigned int next_dma_buf, samplesinbuf, sampls, m;
00605 
00606         if (int_amcc & MASTER_ABORT_INT) {
00607                 comedi_error(dev, "AMCC IRQ - MASTER DMA ABORT!");
00608                 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
00609                 pci9118_ai_cancel(dev, s);
00610                 comedi_event(dev, s);
00611                 return;
00612         }
00613 
00614         if (int_amcc & TARGET_ABORT_INT) {
00615                 comedi_error(dev, "AMCC IRQ - TARGET DMA ABORT!");
00616                 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
00617                 pci9118_ai_cancel(dev, s);
00618                 comedi_event(dev, s);
00619                 return;
00620         }
00621 
00622         if (int_adstat & devpriv->ai_maskerr)
00623 //      if (int_adstat & 0x106)
00624                 if (pci9118_decode_error_status(dev, s, int_adstat))
00625                         return;
00626 
00627         samplesinbuf = devpriv->dmabuf_use_size[devpriv->dma_actbuf] >> 1;      // number of received real samples
00628 //      DPRINTK("dma_actbuf=%d\n",devpriv->dma_actbuf);
00629 
00630         if (devpriv->dma_doublebuf) {   // switch DMA buffers if is used double buffering
00631                 next_dma_buf = 1 - devpriv->dma_actbuf;
00632                 outl(devpriv->dmabuf_hw[next_dma_buf],
00633                         devpriv->iobase_a + AMCC_OP_REG_MWAR);
00634                 outl(devpriv->dmabuf_use_size[next_dma_buf],
00635                         devpriv->iobase_a + AMCC_OP_REG_MWTC);
00636                 devpriv->dmabuf_used_size[next_dma_buf] =
00637                         devpriv->dmabuf_use_size[next_dma_buf];
00638                 if (devpriv->ai_do == 4)
00639                         interrupt_pci9118_ai_mode4_switch(dev);
00640         }
00641 
00642         if (samplesinbuf) {
00643                 m = devpriv->ai_data_len >> 1;  // how many samples is to end of buffer
00644 //              DPRINTK("samps=%d m=%d %d %d\n",samplesinbuf,m,s->async->buf_int_count,s->async->buf_int_ptr);
00645                 sampls = m;
00646                 move_block_from_dma(dev, s,
00647                         devpriv->dmabuf_virt[devpriv->dma_actbuf],
00648                         samplesinbuf);
00649                 m = m - sampls; // m= how many samples was transfered
00650         }
00651 //      DPRINTK("YYY\n");
00652 
00653         if (!devpriv->ai_neverending)
00654                 if (devpriv->ai_act_scan >= devpriv->ai_scans) {        /* all data sampled */
00655                         pci9118_ai_cancel(dev, s);
00656                         s->async->events |= COMEDI_CB_EOA;
00657                 }
00658 
00659         if (devpriv->dma_doublebuf) {   // switch dma buffers
00660                 devpriv->dma_actbuf = 1 - devpriv->dma_actbuf;
00661         } else {                // restart DMA if is not used double buffering
00662                 outl(devpriv->dmabuf_hw[0],
00663                         devpriv->iobase_a + AMCC_OP_REG_MWAR);
00664                 outl(devpriv->dmabuf_use_size[0],
00665                         devpriv->iobase_a + AMCC_OP_REG_MWTC);
00666                 if (devpriv->ai_do == 4)
00667                         interrupt_pci9118_ai_mode4_switch(dev);
00668         }
00669 
00670         comedi_event(dev, s);
00671 }
00672 
00673 /*
00674 ==============================================================================
00675 */
00676 static irqreturn_t interrupt_pci9118(int irq, void *d PT_REGS_ARG)
00677 {
00678         comedi_device *dev = d;
00679         unsigned int int_daq = 0, int_amcc, int_adstat;
00680 
00681         if (!dev->attached)
00682                 return IRQ_NONE;        // not fully initialized
00683 
00684         int_daq = inl(dev->iobase + PCI9118_INTSRC) & 0xf;      // get IRQ reasons from card
00685         int_amcc = inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR); // get INT register from AMCC chip
00686 
00687 //      DPRINTK("INT daq=0x%01x amcc=0x%08x MWAR=0x%08x MWTC=0x%08x ADSTAT=0x%02x ai_do=%d\n", int_daq, int_amcc, inl(devpriv->iobase_a+AMCC_OP_REG_MWAR), inl(devpriv->iobase_a+AMCC_OP_REG_MWTC), inw(dev->iobase+PCI9118_ADSTAT)&0x1ff,devpriv->ai_do);
00688 
00689         if ((!int_daq) && (!(int_amcc & ANY_S593X_INT)))
00690                 return IRQ_NONE;        // interrupt from other source
00691 
00692         outl(int_amcc | 0x00ff0000, devpriv->iobase_a + AMCC_OP_REG_INTCSR);    // shutdown IRQ reasons in AMCC
00693 
00694         int_adstat = inw(dev->iobase + PCI9118_ADSTAT) & 0x1ff; // get STATUS register
00695 
00696         if (devpriv->ai_do) {
00697                 if (devpriv->ai12_startstop)
00698                         if ((int_adstat & AdStatus_DTH) && (int_daq & Int_DTrg)) {      // start stop of measure
00699                                 if (devpriv->ai12_startstop & START_AI_EXT) {
00700                                         devpriv->ai12_startstop &=
00701                                                 ~START_AI_EXT;
00702                                         if (!(devpriv->ai12_startstop &
00703                                                         STOP_AI_EXT))
00704                                                 pci9118_exttrg_del(dev, EXTTRG_AI);     // deactivate EXT trigger
00705                                         start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1, devpriv->ai_divisor2);   // start pacer
00706                                         outl(devpriv->AdControlReg,
00707                                                 dev->iobase + PCI9118_ADCNTRL);
00708                                 } else {
00709                                         if (devpriv->
00710                                                 ai12_startstop & STOP_AI_EXT) {
00711                                                 devpriv->ai12_startstop &=
00712                                                         ~STOP_AI_EXT;
00713                                                 pci9118_exttrg_del(dev, EXTTRG_AI);     // deactivate EXT trigger
00714                                                 devpriv->ai_neverending = 0;    //well, on next interrupt from DMA/EOC measure will stop
00715                                         }
00716                                 }
00717                         }
00718 
00719                 (devpriv->int_ai_func) (dev, dev->subdevices + 0, int_adstat,
00720                         int_amcc, int_daq);
00721 
00722         }
00723         return IRQ_HANDLED;
00724 }
00725 
00726 /*
00727 ==============================================================================
00728 */
00729 static int pci9118_ai_inttrig(comedi_device * dev, comedi_subdevice * s,
00730         unsigned int trignum)
00731 {
00732         if (trignum != devpriv->ai_inttrig_start)
00733                 return -EINVAL;
00734 
00735         devpriv->ai12_startstop &= ~START_AI_INT;
00736         s->async->inttrig = NULL;
00737 
00738         outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
00739         outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
00740         if (devpriv->ai_do != 3) {
00741                 start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1,
00742                         devpriv->ai_divisor2);
00743                 devpriv->AdControlReg |= AdControl_SoftG;
00744         }
00745         outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
00746 
00747         return 1;
00748 }
00749 
00750 /*
00751 ==============================================================================
00752 */
00753 static int pci9118_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
00754         comedi_cmd * cmd)
00755 {
00756         int err = 0;
00757         int tmp, divisor1, divisor2;
00758 
00759         /* step 1: make sure trigger sources are trivially valid */
00760 
00761         tmp = cmd->start_src;
00762         cmd->start_src &= TRIG_NOW | TRIG_EXT | TRIG_INT;
00763         if (!cmd->start_src || tmp != cmd->start_src)
00764                 err++;
00765 
00766         tmp = cmd->scan_begin_src;
00767         if (devpriv->master) {
00768                 cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT | TRIG_FOLLOW;
00769         } else {
00770                 cmd->scan_begin_src &= TRIG_FOLLOW;
00771         }
00772         if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
00773                 err++;
00774 
00775         tmp = cmd->convert_src;
00776         if (devpriv->master) {
00777                 cmd->convert_src &= TRIG_TIMER | TRIG_EXT | TRIG_NOW;
00778         } else {
00779                 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
00780         }
00781         if (!cmd->convert_src || tmp != cmd->convert_src)
00782                 err++;
00783 
00784         tmp = cmd->scan_end_src;
00785         cmd->scan_end_src &= TRIG_COUNT;
00786         if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
00787                 err++;
00788 
00789         tmp = cmd->stop_src;
00790         cmd->stop_src &= TRIG_COUNT | TRIG_NONE | TRIG_EXT;
00791         if (!cmd->stop_src || tmp != cmd->stop_src)
00792                 err++;
00793 
00794         if (err)
00795                 return 1;
00796 
00797         /* step 2: make sure trigger sources are unique and mutually compatible */
00798 
00799         if (cmd->start_src != TRIG_NOW &&
00800                 cmd->start_src != TRIG_INT && cmd->start_src != TRIG_EXT) {
00801                 cmd->start_src = TRIG_NOW;
00802                 err++;
00803         }
00804 
00805         if (cmd->scan_begin_src != TRIG_TIMER &&
00806                 cmd->scan_begin_src != TRIG_EXT &&
00807                 cmd->scan_begin_src != TRIG_INT &&
00808                 cmd->scan_begin_src != TRIG_FOLLOW) {
00809                 cmd->scan_begin_src = TRIG_FOLLOW;
00810                 err++;
00811         }
00812 
00813         if (cmd->convert_src != TRIG_TIMER &&
00814                 cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW) {
00815                 cmd->convert_src = TRIG_TIMER;
00816                 err++;
00817         }
00818 
00819         if (cmd->scan_end_src != TRIG_COUNT) {
00820                 cmd->scan_end_src = TRIG_COUNT;
00821                 err++;
00822         }
00823 
00824         if (cmd->stop_src != TRIG_NONE &&
00825                 cmd->stop_src != TRIG_COUNT &&
00826                 cmd->stop_src != TRIG_INT && cmd->stop_src != TRIG_EXT) {
00827                 cmd->stop_src = TRIG_COUNT;
00828                 err++;
00829         }
00830 
00831         if (cmd->start_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT) {
00832                 cmd->start_src = TRIG_NOW;
00833                 err++;
00834         }
00835 
00836         if (cmd->start_src == TRIG_INT && cmd->scan_begin_src == TRIG_INT) {
00837                 cmd->start_src = TRIG_NOW;
00838                 err++;
00839         }
00840 
00841         if ((cmd->scan_begin_src & (TRIG_TIMER | TRIG_EXT)) &&
00842                 (!(cmd->convert_src & (TRIG_TIMER | TRIG_NOW)))) {
00843                 cmd->convert_src = TRIG_TIMER;
00844                 err++;
00845         }
00846 
00847         if ((cmd->scan_begin_src == TRIG_FOLLOW) &&
00848                 (!(cmd->convert_src & (TRIG_TIMER | TRIG_EXT)))) {
00849                 cmd->convert_src = TRIG_TIMER;
00850                 err++;
00851         }
00852 
00853         if (cmd->stop_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT) {
00854                 cmd->stop_src = TRIG_COUNT;
00855                 err++;
00856         }
00857 
00858         if (err)
00859                 return 2;
00860 
00861         /* step 3: make sure arguments are trivially compatible */
00862 
00863         if (cmd->start_src & (TRIG_NOW | TRIG_EXT))
00864                 if (cmd->start_arg != 0) {
00865                         cmd->start_arg = 0;
00866                         err++;
00867                 }
00868 
00869         if (cmd->scan_begin_src & (TRIG_FOLLOW | TRIG_EXT))
00870                 if (cmd->scan_begin_arg != 0) {
00871                         cmd->scan_begin_arg = 0;
00872                         err++;
00873                 }
00874 
00875         if ((cmd->scan_begin_src == TRIG_TIMER) &&
00876                 (cmd->convert_src == TRIG_TIMER) && (cmd->scan_end_arg == 1)) {
00877                 cmd->scan_begin_src = TRIG_FOLLOW;
00878                 cmd->convert_arg = cmd->scan_begin_arg;
00879                 cmd->scan_begin_arg = 0;
00880         }
00881 
00882         if (cmd->scan_begin_src == TRIG_TIMER)
00883                 if (cmd->scan_begin_arg < this_board->ai_ns_min) {
00884                         cmd->scan_begin_arg = this_board->ai_ns_min;
00885                         err++;
00886                 }
00887 
00888         if (cmd->scan_begin_src == TRIG_EXT)
00889                 if (cmd->scan_begin_arg) {
00890                         cmd->scan_begin_arg = 0;
00891                         err++;
00892                         if (cmd->scan_end_arg > 65535) {
00893                                 cmd->scan_end_arg = 65535;
00894                                 err++;
00895                         }
00896                 }
00897 
00898         if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW))
00899                 if (cmd->convert_arg < this_board->ai_ns_min) {
00900                         cmd->convert_arg = this_board->ai_ns_min;
00901                         err++;
00902                 }
00903 
00904         if (cmd->convert_src == TRIG_EXT)
00905                 if (cmd->convert_arg) {
00906                         cmd->convert_arg = 0;
00907                         err++;
00908                 }
00909 
00910         if (cmd->stop_src == TRIG_COUNT) {
00911                 if (!cmd->stop_arg) {
00912                         cmd->stop_arg = 1;
00913                         err++;
00914                 }
00915         } else {                /* TRIG_NONE */
00916                 if (cmd->stop_arg != 0) {
00917                         cmd->stop_arg = 0;
00918                         err++;
00919                 }
00920         }
00921 
00922         if (!cmd->chanlist_len) {
00923                 cmd->chanlist_len = 1;
00924                 err++;
00925         }
00926 
00927         if (cmd->chanlist_len > this_board->n_aichanlist) {
00928                 cmd->chanlist_len = this_board->n_aichanlist;
00929                 err++;
00930         }
00931 
00932         if (cmd->scan_end_arg < cmd->chanlist_len) {
00933                 cmd->scan_end_arg = cmd->chanlist_len;
00934                 err++;
00935         }
00936 
00937         if ((cmd->scan_end_arg % cmd->chanlist_len)) {
00938                 cmd->scan_end_arg =
00939                         cmd->chanlist_len * (cmd->scan_end_arg /
00940                         cmd->chanlist_len);
00941                 err++;
00942         }
00943 
00944         if (err)
00945                 return 3;
00946 
00947         /* step 4: fix up any arguments */
00948 
00949         if (cmd->scan_begin_src == TRIG_TIMER) {
00950                 tmp = cmd->scan_begin_arg;
00951 //              rt_printk("S1 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg);
00952                 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
00953                         &divisor2, &cmd->scan_begin_arg,
00954                         cmd->flags & TRIG_ROUND_MASK);
00955 //              rt_printk("S2 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg);
00956                 if (cmd->scan_begin_arg < this_board->ai_ns_min)
00957                         cmd->scan_begin_arg = this_board->ai_ns_min;
00958                 if (tmp != cmd->scan_begin_arg)
00959                         err++;
00960         }
00961 
00962         if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW)) {
00963                 tmp = cmd->convert_arg;
00964                 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
00965                         &divisor2, &cmd->convert_arg,
00966                         cmd->flags & TRIG_ROUND_MASK);
00967 //              rt_printk("s1 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg);
00968                 if (cmd->convert_arg < this_board->ai_ns_min)
00969                         cmd->convert_arg = this_board->ai_ns_min;
00970                 if (tmp != cmd->convert_arg)
00971                         err++;
00972                 if (cmd->scan_begin_src == TRIG_TIMER
00973                         && cmd->convert_src == TRIG_NOW) {
00974                         if (cmd->convert_arg == 0) {
00975                                 if (cmd->scan_begin_arg <
00976                                         this_board->ai_ns_min *
00977                                         (cmd->scan_end_arg + 2)) {
00978                                         cmd->scan_begin_arg =
00979                                                 this_board->ai_ns_min *
00980                                                 (cmd->scan_end_arg + 2);
00981 //              rt_printk("s2 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg);
00982                                         err++;
00983                                 }
00984                         } else {
00985                                 if (cmd->scan_begin_arg <
00986                                         cmd->convert_arg * cmd->chanlist_len) {
00987                                         cmd->scan_begin_arg =
00988                                                 cmd->convert_arg *
00989                                                 cmd->chanlist_len;
00990 //              rt_printk("s3 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg);
00991                                         err++;
00992                                 }
00993                         }
00994                 }
00995         }
00996 
00997         if (err)
00998                 return 4;
00999 
01000         if (cmd->chanlist)
01001                 if (!check_channel_list(dev, s, cmd->chanlist_len,
01002                                 cmd->chanlist, 0, 0))
01003                         return 5;       // incorrect channels list
01004 
01005         return 0;
01006 }
01007 
01008 /*
01009 ==============================================================================
01010 */
01011 static int Compute_and_setup_dma(comedi_device * dev)
01012 {
01013         unsigned int dmalen0, dmalen1, i;
01014 
01015         DPRINTK("adl_pci9118 EDBG: BGN: Compute_and_setup_dma()\n");
01016         dmalen0 = devpriv->dmabuf_size[0];
01017         dmalen1 = devpriv->dmabuf_size[1];
01018         DPRINTK("1 dmalen0=%d dmalen1=%d ai_data_len=%d\n", dmalen0, dmalen1,
01019                 devpriv->ai_data_len);
01020         // isn't output buff smaller that our DMA buff?
01021         if (dmalen0 > (devpriv->ai_data_len)) {
01022                 dmalen0 = devpriv->ai_data_len & ~3L;   // allign to 32bit down
01023         }
01024         if (dmalen1 > (devpriv->ai_data_len)) {
01025                 dmalen1 = devpriv->ai_data_len & ~3L;   // allign to 32bit down
01026         }
01027         DPRINTK("2 dmalen0=%d dmalen1=%d \n", dmalen0, dmalen1);
01028 
01029         // we want wake up every scan?
01030         if (devpriv->ai_flags & TRIG_WAKE_EOS) {
01031                 if (dmalen0 < (devpriv->ai_n_realscanlen << 1)) {
01032                         // uff, too short DMA buffer, disable EOS support!
01033                         devpriv->ai_flags &= (~TRIG_WAKE_EOS);
01034                         rt_printk
01035                                 ("comedi%d: WAR: DMA0 buf too short, cann't support TRIG_WAKE_EOS (%d<%d)\n",
01036                                 dev->minor, dmalen0,
01037                                 devpriv->ai_n_realscanlen << 1);
01038                 } else {
01039                         // short first DMA buffer to one scan
01040                         dmalen0 = devpriv->ai_n_realscanlen << 1;
01041                         DPRINTK("21 dmalen0=%d ai_n_realscanlen=%d useeoshandle=%d\n", dmalen0, devpriv->ai_n_realscanlen, devpriv->useeoshandle);
01042                         if (devpriv->useeoshandle)
01043                                 dmalen0 += 2;
01044                         if (dmalen0 < 4) {
01045                                 rt_printk
01046                                         ("comedi%d: ERR: DMA0 buf len bug? (%d<4)\n",
01047                                         dev->minor, dmalen0);
01048                                 dmalen0 = 4;
01049                         }
01050                 }
01051         }
01052         if (devpriv->ai_flags & TRIG_WAKE_EOS) {
01053                 if (dmalen1 < (devpriv->ai_n_realscanlen << 1)) {
01054                         // uff, too short DMA buffer, disable EOS support!
01055                         devpriv->ai_flags &= (~TRIG_WAKE_EOS);
01056                         rt_printk
01057                                 ("comedi%d: WAR: DMA1 buf too short, cann't support TRIG_WAKE_EOS (%d<%d)\n",
01058                                 dev->minor, dmalen1,
01059                                 devpriv->ai_n_realscanlen << 1);
01060                 } else {
01061                         // short second DMA buffer to one scan
01062                         dmalen1 = devpriv->ai_n_realscanlen << 1;
01063                         DPRINTK("22 dmalen1=%d ai_n_realscanlen=%d useeoshandle=%d\n", dmalen1, devpriv->ai_n_realscanlen, devpriv->useeoshandle);
01064                         if (devpriv->useeoshandle)
01065                                 dmalen1 -= 2;
01066                         if (dmalen1 < 4) {
01067                                 rt_printk
01068                                         ("comedi%d: ERR: DMA1 buf len bug? (%d<4)\n",
01069                                         dev->minor, dmalen1);
01070                                 dmalen1 = 4;
01071                         }
01072                 }
01073         }
01074 
01075         DPRINTK("3 dmalen0=%d dmalen1=%d \n", dmalen0, dmalen1);
01076         // transfer without TRIG_WAKE_EOS
01077         if (!(devpriv->ai_flags & TRIG_WAKE_EOS)) {
01078                 // if it's possible then allign DMA buffers to length of scan
01079                 i = dmalen0;
01080                 dmalen0 =
01081                         (dmalen0 / (devpriv->ai_n_realscanlen << 1)) *
01082                         (devpriv->ai_n_realscanlen << 1);
01083                 dmalen0 &= ~3L;
01084                 if (!dmalen0)
01085                         dmalen0 = i;    // uff. very long scan?
01086                 i = dmalen1;
01087                 dmalen1 =
01088                         (dmalen1 / (devpriv->ai_n_realscanlen << 1)) *
01089                         (devpriv->ai_n_realscanlen << 1);
01090                 dmalen1 &= ~3L;
01091                 if (!dmalen1)
01092                         dmalen1 = i;    // uff. very long scan?
01093                 // if measure isn't neverending then test, if it whole fits into one or two DMA buffers
01094                 if (!devpriv->ai_neverending) {
01095                         // fits whole measure into one DMA buffer?
01096                         if (dmalen0 >
01097                                 ((devpriv->ai_n_realscanlen << 1) *
01098                                         devpriv->ai_scans)) {
01099                                 DPRINTK("3.0 ai_n_realscanlen=%d ai_scans=%d \n", devpriv->ai_n_realscanlen, devpriv->ai_scans);
01100                                 dmalen0 =
01101                                         (devpriv->ai_n_realscanlen << 1) *
01102                                         devpriv->ai_scans;
01103                                 DPRINTK("3.1 dmalen0=%d dmalen1=%d \n", dmalen0,
01104                                         dmalen1);
01105                                 dmalen0 &= ~3L;
01106                         } else {        // fits whole measure into two DMA buffer?
01107                                 if (dmalen1 >
01108                                         ((devpriv->ai_n_realscanlen << 1) *
01109                                                 devpriv->ai_scans - dmalen0))
01110                                         dmalen1 =
01111                                                 (devpriv->
01112                                                 ai_n_realscanlen << 1) *
01113                                                 devpriv->ai_scans - dmalen0;
01114                                 DPRINTK("3.2 dmalen0=%d dmalen1=%d \n", dmalen0,
01115                                         dmalen1);
01116                                 dmalen1 &= ~3L;
01117                         }
01118                 }
01119         }
01120 
01121         DPRINTK("4 dmalen0=%d dmalen1=%d \n", dmalen0, dmalen1);
01122 
01123         // these DMA buffer size we'll be used
01124         devpriv->dma_actbuf = 0;
01125         devpriv->dmabuf_use_size[0] = dmalen0;
01126         devpriv->dmabuf_use_size[1] = dmalen1;
01127 
01128         DPRINTK("5 dmalen0=%d dmalen1=%d \n", dmalen0, dmalen1);
01129 #if 0
01130         if (devpriv->ai_n_scanlen < this_board->half_fifo_size) {
01131                 devpriv->dmabuf_panic_size[0] =
01132                         (this_board->half_fifo_size / devpriv->ai_n_scanlen +
01133                         1) * devpriv->ai_n_scanlen * sizeof(sampl_t);
01134                 devpriv->dmabuf_panic_size[1] =
01135                         (this_board->half_fifo_size / devpriv->ai_n_scanlen +
01136                         1) * devpriv->ai_n_scanlen * sizeof(sampl_t);
01137         } else {
01138                 devpriv->dmabuf_panic_size[0] =
01139                         (devpriv->ai_n_scanlen << 1) % devpriv->dmabuf_size[0];
01140                 devpriv->dmabuf_panic_size[1] =
01141                         (devpriv->ai_n_scanlen << 1) % devpriv->dmabuf_size[1];
01142         }
01143 #endif
01144 
01145         outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) & (~EN_A2P_TRANSFERS), devpriv->iobase_a + AMCC_OP_REG_MCSR);    // stop DMA
01146         outl(devpriv->dmabuf_hw[0], devpriv->iobase_a + AMCC_OP_REG_MWAR);
01147         outl(devpriv->dmabuf_use_size[0], devpriv->iobase_a + AMCC_OP_REG_MWTC);
01148         // init DMA transfer
01149         outl(0x00000000 | AINT_WRITE_COMPL,
01150                 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
01151 //      outl(0x02000000|AINT_WRITE_COMPL, devpriv->iobase_a+AMCC_OP_REG_INTCSR);
01152 
01153         outl(inl(devpriv->iobase_a +
01154                         AMCC_OP_REG_MCSR) | RESET_A2P_FLAGS | A2P_HI_PRIORITY |
01155                 EN_A2P_TRANSFERS, devpriv->iobase_a + AMCC_OP_REG_MCSR);
01156         outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | EN_A2P_TRANSFERS, devpriv->iobase_a + AMCC_OP_REG_INTCSR);   // allow bus mastering
01157 
01158         DPRINTK("adl_pci9118 EDBG: END: Compute_and_setup_dma()\n");
01159         return 0;
01160 }
01161 
01162 /*
01163 ==============================================================================
01164 */
01165 static int pci9118_ai_docmd_sampl(comedi_device * dev, comedi_subdevice * s)
01166 {
01167         DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_sampl(%d,) [%d]\n",
01168                 dev->minor, devpriv->ai_do);
01169         switch (devpriv->ai_do) {
01170         case 1:
01171                 devpriv->AdControlReg |= AdControl_TmrTr;
01172                 break;
01173         case 2:
01174                 comedi_error(dev, "pci9118_ai_docmd_sampl() mode 2 bug!\n");
01175                 return -EIO;
01176         case 3:
01177                 devpriv->AdControlReg |= AdControl_ExtM;
01178                 break;
01179         case 4:
01180                 comedi_error(dev, "pci9118_ai_docmd_sampl() mode 4 bug!\n");
01181                 return -EIO;
01182         default:
01183                 comedi_error(dev,
01184                         "pci9118_ai_docmd_sampl() mode number bug!\n");
01185                 return -EIO;
01186         };
01187 
01188         devpriv->int_ai_func = interrupt_pci9118_ai_onesample;  //transfer function
01189 
01190         if (devpriv->ai12_startstop)
01191                 pci9118_exttrg_add(dev, EXTTRG_AI);     // activate EXT trigger
01192 
01193         if ((devpriv->ai_do == 1) || (devpriv->ai_do == 2))
01194                 devpriv->IntControlReg |= Int_Timer;
01195 
01196         devpriv->AdControlReg |= AdControl_Int;
01197 
01198         outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00, devpriv->iobase_a + AMCC_OP_REG_INTCSR);     // allow INT in AMCC
01199 
01200         if (!(devpriv->ai12_startstop & (START_AI_EXT | START_AI_INT))) {
01201                 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
01202                 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
01203                 if (devpriv->ai_do != 3) {
01204                         start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1,
01205                                 devpriv->ai_divisor2);
01206                         devpriv->AdControlReg |= AdControl_SoftG;
01207                 }
01208                 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
01209         }
01210 
01211         DPRINTK("adl_pci9118 EDBG: END: pci9118_ai_docmd_sampl()\n");
01212         return 0;
01213 }
01214 
01215 /*
01216 ==============================================================================
01217 */
01218 static int pci9118_ai_docmd_dma(comedi_device * dev, comedi_subdevice * s)
01219 {
01220         DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_dma(%d,) [%d,%d]\n",
01221                 dev->minor, devpriv->ai_do, devpriv->usedma);
01222         Compute_and_setup_dma(dev);
01223 
01224         switch (devpriv->ai_do) {
01225         case 1:
01226                 devpriv->AdControlReg |=
01227                         ((AdControl_TmrTr | AdControl_Dma) & 0xff);
01228                 break;
01229         case 2:
01230                 devpriv->AdControlReg |=
01231                         ((AdControl_TmrTr | AdControl_Dma) & 0xff);
01232                 devpriv->AdFunctionReg =
01233                         AdFunction_PDTrg | AdFunction_PETrg | AdFunction_BM |
01234                         AdFunction_BS;
01235                 if (devpriv->usessh && (!devpriv->softsshdelay))
01236                         devpriv->AdFunctionReg |= AdFunction_BSSH;
01237                 outl(devpriv->ai_n_realscanlen, dev->iobase + PCI9118_BURST);
01238                 break;
01239         case 3:
01240                 devpriv->AdControlReg |=
01241                         ((AdControl_ExtM | AdControl_Dma) & 0xff);
01242                 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
01243                 break;
01244         case 4:
01245                 devpriv->AdControlReg |=
01246                         ((AdControl_TmrTr | AdControl_Dma) & 0xff);
01247                 devpriv->AdFunctionReg =
01248                         AdFunction_PDTrg | AdFunction_PETrg | AdFunction_AM;
01249                 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
01250                 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
01251                 outl((devpriv->dmabuf_hw[0] >> 1) & 0xff,
01252                         dev->iobase + PCI9118_CNT0);
01253                 outl((devpriv->dmabuf_hw[0] >> 9) & 0xff,
01254                         dev->iobase + PCI9118_CNT0);
01255                 devpriv->AdFunctionReg |= AdFunction_Start;
01256                 break;
01257         default:
01258                 comedi_error(dev, "pci9118_ai_docmd_dma() mode number bug!\n");
01259                 return -EIO;
01260         };
01261 
01262         if (devpriv->ai12_startstop) {
01263                 pci9118_exttrg_add(dev, EXTTRG_AI);     // activate EXT trigger
01264         }
01265 
01266         devpriv->int_ai_func = interrupt_pci9118_ai_dma;        //transfer function
01267 
01268         outl(0x02000000 | AINT_WRITE_COMPL,
01269                 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
01270 
01271         if (!(devpriv->ai12_startstop & (START_AI_EXT | START_AI_INT))) {
01272                 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
01273                 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
01274                 if (devpriv->ai_do != 3) {
01275                         start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1,
01276                                 devpriv->ai_divisor2);
01277                         devpriv->AdControlReg |= AdControl_SoftG;
01278                 }
01279                 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
01280         }
01281 
01282         DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_dma()\n");
01283         return 0;
01284 }
01285 
01286 /*
01287 ==============================================================================
01288 */
01289 static int pci9118_ai_cmd(comedi_device * dev, comedi_subdevice * s)
01290 {
01291         comedi_cmd *cmd = &s->async->cmd;
01292         unsigned int addchans = 0;
01293         int ret = 0;
01294 
01295         DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_cmd(%d,)\n", dev->minor);
01296         devpriv->ai12_startstop = 0;
01297         devpriv->ai_flags = cmd->flags;
01298         devpriv->ai_n_chan = cmd->chanlist_len;
01299         devpriv->ai_n_scanlen = cmd->scan_end_arg;
01300         devpriv->ai_chanlist = cmd->chanlist;
01301         devpriv->ai_data = s->async->prealloc_buf;
01302         devpriv->ai_data_len = s->async->prealloc_bufsz;
01303         devpriv->ai_timer1 = 0;
01304         devpriv->ai_timer2 = 0;
01305         devpriv->ai_add_front = 0;
01306         devpriv->ai_add_back = 0;
01307         devpriv->ai_maskerr = 0x10e;
01308 
01309         // prepare for start/stop conditions
01310         if (cmd->start_src == TRIG_EXT)
01311                 devpriv->ai12_startstop |= START_AI_EXT;
01312         if (cmd->stop_src == TRIG_EXT) {
01313                 devpriv->ai_neverending = 1;
01314                 devpriv->ai12_startstop |= STOP_AI_EXT;
01315         }
01316         if (cmd->start_src == TRIG_INT) {
01317                 devpriv->ai12_startstop |= START_AI_INT;
01318                 devpriv->ai_inttrig_start = cmd->start_arg;
01319                 s->async->inttrig = pci9118_ai_inttrig;
01320         }
01321 #if 0
01322         if (cmd->stop_src == TRIG_INT) {
01323                 devpriv->ai_neverending = 1;
01324                 devpriv->ai12_startstop |= STOP_AI_INT;
01325         }
01326 #endif
01327         if (cmd->stop_src == TRIG_NONE)
01328                 devpriv->ai_neverending = 1;
01329         if (cmd->stop_src == TRIG_COUNT) {
01330                 devpriv->ai_scans = cmd->stop_arg;
01331                 devpriv->ai_neverending = 0;
01332         } else {
01333                 devpriv->ai_scans = 0;
01334         }
01335 
01336         // use sample&hold signal?
01337         if (cmd->convert_src == TRIG_NOW) {
01338                 devpriv->usessh = 1;
01339         }                       // yes
01340         else {
01341                 devpriv->usessh = 0;
01342         }                       // no
01343 
01344         DPRINTK("1 neverending=%d scans=%u usessh=%d ai_startstop=0x%2x\n",
01345                 devpriv->ai_neverending, devpriv->ai_scans, devpriv->usessh,
01346                 devpriv->ai12_startstop);
01347 
01348         // use additional sample at end of every scan to satisty DMA 32 bit transfer?
01349         devpriv->ai_add_front = 0;
01350         devpriv->ai_add_back = 0;
01351         devpriv->useeoshandle = 0;
01352         if (devpriv->master) {
01353                 devpriv->usedma = 1;
01354                 if ((cmd->flags & TRIG_WAKE_EOS) &&
01355                         (devpriv->ai_n_scanlen == 1)) {
01356                         if (cmd->convert_src == TRIG_NOW) {
01357                                 devpriv->ai_add_back = 1;
01358                         }
01359                         if (cmd->convert_src == TRIG_TIMER) {
01360                                 devpriv->usedma = 0;    // use INT transfer if scanlist have only one channel
01361                         }
01362                 }
01363                 if ((cmd->flags & TRIG_WAKE_EOS) &&
01364                         (devpriv->ai_n_scanlen & 1) &&
01365                         (devpriv->ai_n_scanlen > 1)) {
01366                         if (cmd->scan_begin_src == TRIG_FOLLOW) {
01367                                 //vpriv->useeoshandle=1; // change DMA transfer block to fit EOS on every second call
01368                                 devpriv->usedma = 0;    // XXX maybe can be corrected to use 16 bit DMA
01369                         } else {        // well, we must insert one sample to end of EOS to meet 32 bit transfer
01370                                 devpriv->ai_add_back = 1;
01371                         }
01372                 }
01373         } else {                // interrupt transfer don't need any correction
01374                 devpriv->usedma = 0;
01375         }
01376 
01377         // we need software S&H signal? It add  two samples before every scan as minimum
01378         if (devpriv->usessh && devpriv->softsshdelay) {
01379                 devpriv->ai_add_front = 2;
01380                 if ((devpriv->usedma == 1) && (devpriv->ai_add_back == 1)) {    // move it to front
01381                         devpriv->ai_add_front++;
01382                         devpriv->ai_add_back = 0;
01383                 }
01384                 if (cmd->convert_arg < this_board->ai_ns_min)
01385                         cmd->convert_arg = this_board->ai_ns_min;
01386                 addchans = devpriv->softsshdelay / cmd->convert_arg;
01387                 if (devpriv->softsshdelay % cmd->convert_arg)
01388                         addchans++;
01389                 if (addchans > (devpriv->ai_add_front - 1)) {   // uff, still short :-(
01390                         devpriv->ai_add_front = addchans + 1;
01391                         if (devpriv->usedma == 1)
01392                                 if ((devpriv->ai_add_front +
01393                                                 devpriv->ai_n_chan +
01394                                                 devpriv->ai_add_back) & 1)
01395                                         devpriv->ai_add_front++;        // round up to 32 bit
01396                 }
01397         }                       // well, we now know what must be all added
01398 
01399         devpriv->ai_n_realscanlen =     // what we must take from card in real to have ai_n_scanlen on output?
01400                 (devpriv->ai_add_front + devpriv->ai_n_chan +
01401                 devpriv->ai_add_back) * (devpriv->ai_n_scanlen /
01402                 devpriv->ai_n_chan);
01403 
01404         DPRINTK("2 usedma=%d realscan=%d af=%u n_chan=%d ab=%d n_scanlen=%d\n",
01405                 devpriv->usedma,
01406                 devpriv->ai_n_realscanlen, devpriv->ai_add_front,
01407                 devpriv->ai_n_chan, devpriv->ai_add_back,
01408                 devpriv->ai_n_scanlen);
01409 
01410         // check and setup channel list
01411         if (!check_channel_list(dev, s, devpriv->ai_n_chan,
01412                         devpriv->ai_chanlist, devpriv->ai_add_front,
01413                         devpriv->ai_add_back))
01414                 return -EINVAL;
01415         if (!setup_channel_list(dev, s, devpriv->ai_n_chan,
01416                         devpriv->ai_chanlist, 0, devpriv->ai_add_front,
01417                         devpriv->ai_add_back, devpriv->usedma,
01418                         devpriv->useeoshandle))
01419                 return -EINVAL;
01420 
01421         // compute timers settings
01422         // simplest way, fr=4Mhz/(tim1*tim2), channel manipulation without timers effect
01423         if (((cmd->scan_begin_src == TRIG_FOLLOW) || (cmd->scan_begin_src == TRIG_EXT) || (cmd->scan_begin_src == TRIG_INT)) && (cmd->convert_src == TRIG_TIMER)) {     // both timer is used for one time
01424                 if (cmd->scan_begin_src == TRIG_EXT) {
01425                         devpriv->ai_do = 4;
01426                 } else {
01427                         devpriv->ai_do = 1;
01428                 }
01429                 pci9118_calc_divisors(devpriv->ai_do, dev, s,
01430                         &cmd->scan_begin_arg, &cmd->convert_arg,
01431                         devpriv->ai_flags, devpriv->ai_n_realscanlen,
01432                         &devpriv->ai_divisor1, &devpriv->ai_divisor2,
01433                         devpriv->usessh, devpriv->ai_add_front);
01434                 devpriv->ai_timer2 = cmd->convert_arg;
01435         }
01436 
01437         if ((cmd->scan_begin_src == TRIG_TIMER) && ((cmd->convert_src == TRIG_TIMER) || (cmd->convert_src == TRIG_NOW))) {      // double timed action
01438                 if (!devpriv->usedma) {
01439                         comedi_error(dev,
01440                                 "cmd->scan_begin_src=TRIG_TIMER works only with bus mastering!");
01441                         return -EIO;
01442                 }
01443 
01444                 devpriv->ai_do = 2;
01445                 pci9118_calc_divisors(devpriv->ai_do, dev, s,
01446                         &cmd->scan_begin_arg, &cmd->convert_arg,
01447                         devpriv->ai_flags, devpriv->ai_n_realscanlen,
01448                         &devpriv->ai_divisor1, &devpriv->ai_divisor2,
01449                         devpriv->usessh, devpriv->ai_add_front);
01450                 devpriv->ai_timer1 = cmd->scan_begin_arg;
01451                 devpriv->ai_timer2 = cmd->convert_arg;
01452         }
01453 
01454         if ((cmd->scan_begin_src == TRIG_FOLLOW)
01455                 && (cmd->convert_src == TRIG_EXT)) {
01456                 devpriv->ai_do = 3;
01457         }
01458 
01459         start_pacer(dev, -1, 0, 0);     // stop pacer
01460 
01461         devpriv->AdControlReg = 0;      // bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable DMA
01462         outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
01463         devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;   // positive triggers, no S&H, no burst, burst stop, no post trigger, no about trigger, trigger stop
01464         outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
01465         comedi_udelay(1);
01466         outl(0, dev->iobase + PCI9118_DELFIFO); // flush FIFO
01467         inl(dev->iobase + PCI9118_ADSTAT);      // flush A/D and INT status register
01468         inl(dev->iobase + PCI9118_INTSRC);
01469 
01470         devpriv->ai_act_scan = 0;
01471         devpriv->ai_act_dmapos = 0;
01472         s->async->cur_chan = 0;
01473         devpriv->ai_buf_ptr = 0;
01474 
01475         if (devpriv->usedma) {
01476                 ret = pci9118_ai_docmd_dma(dev, s);
01477         } else {
01478                 ret = pci9118_ai_docmd_sampl(dev, s);
01479         }
01480 
01481         DPRINTK("adl_pci9118 EDBG: END: pci9118_ai_cmd()\n");
01482         return ret;
01483 }
01484 
01485 /*
01486 ==============================================================================
01487 */
01488 static int check_channel_list(comedi_device * dev, comedi_subdevice * s,
01489         int n_chan, unsigned int *chanlist, int frontadd, int backadd)
01490 {
01491         unsigned int i, differencial = 0, bipolar = 0;
01492 
01493         /* correct channel and range number check itself comedi/range.c */
01494         if (n_chan < 1) {
01495                 comedi_error(dev, "range/channel list is empty!");
01496                 return 0;
01497         }
01498         if ((frontadd + n_chan + backadd) > s->len_chanlist) {
01499                 rt_printk
01500                         ("comedi%d: range/channel list is too long for actual configuration (%d>%d)!",
01501                         dev->minor, n_chan,
01502                         s->len_chanlist - frontadd - backadd);
01503                 return 0;
01504         }
01505 
01506         if (CR_AREF(chanlist[0]) == AREF_DIFF)
01507                 differencial = 1;       // all input must be diff
01508         if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
01509                 bipolar = 1;    // all input must be bipolar
01510         if (n_chan > 1)
01511                 for (i = 1; i < n_chan; i++) {  // check S.E/diff
01512                         if ((CR_AREF(chanlist[i]) == AREF_DIFF) !=
01513                                 (differencial)) {
01514                                 comedi_error(dev,
01515                                         "Differencial and single ended inputs cann't be mixtured!");
01516                                 return 0;
01517                         }
01518                         if ((CR_RANGE(chanlist[i]) < PCI9118_BIPOLAR_RANGES) !=
01519                                 (bipolar)) {
01520                                 comedi_error(dev,
01521                                         "Bipolar and unipolar ranges cann't be mixtured!");
01522                                 return 0;
01523                         }
01524                         if ((!devpriv->usemux) & (differencial) &
01525                                 (CR_CHAN(chanlist[i]) >=
01526                                         this_board->n_aichand)) {
01527                                 comedi_error(dev,
01528                                         "If AREF_DIFF is used then is available only first 8 channels!");
01529                                 return 0;
01530                         }
01531                 }
01532 
01533         return 1;
01534 }
01535 
01536 /*
01537 ==============================================================================
01538 */
01539 static int setup_channel_list(comedi_device * dev, comedi_subdevice * s,
01540         int n_chan, unsigned int *chanlist, int rot, int frontadd, int backadd,
01541         int usedma, char useeos)
01542 {
01543         unsigned int i, differencial = 0, bipolar = 0;
01544         unsigned int scanquad, gain, ssh = 0x00;
01545 
01546         DPRINTK("adl_pci9118 EDBG: BGN: setup_channel_list(%d,.,%d,.,%d,%d,%d,%d)\n", dev->minor, n_chan, rot, frontadd, backadd, usedma);
01547 
01548         if (usedma == 1) {
01549                 rot = 8;
01550                 usedma = 0;
01551         }
01552 
01553         if (CR_AREF(chanlist[0]) == AREF_DIFF)
01554                 differencial = 1;       // all input must be diff
01555         if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
01556                 bipolar = 1;    // all input must be bipolar
01557 
01558         // All is ok, so we can setup channel/range list
01559 
01560         if (!bipolar) {
01561                 devpriv->AdControlReg |= AdControl_UniP;        // set unibipolar
01562         } else {
01563                 devpriv->AdControlReg &= ((~AdControl_UniP) & 0xff);    // enable bipolar
01564         }
01565 
01566         if (differencial) {
01567                 devpriv->AdControlReg |= AdControl_Diff;        // enable diff inputs
01568         } else {
01569                 devpriv->AdControlReg &= ((~AdControl_Diff) & 0xff);    // set single ended inputs
01570         }
01571 
01572         outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);     // setup mode
01573 
01574         outl(2, dev->iobase + PCI9118_SCANMOD); // gods know why this sequence!
01575         outl(0, dev->iobase + PCI9118_SCANMOD);
01576         outl(1, dev->iobase + PCI9118_SCANMOD);
01577 
01578 #ifdef PCI9118_PARANOIDCHECK
01579         devpriv->chanlistlen = n_chan;
01580         for (i = 0; i < (PCI9118_CHANLEN + 1); i++)
01581                 devpriv->chanlist[i] = 0x55aa;
01582 #endif
01583 
01584         if (frontadd) {         // insert channels for S&H
01585                 ssh = devpriv->softsshsample;
01586                 DPRINTK("FA: %04x: ", ssh);
01587                 for (i = 0; i < frontadd; i++) {        // store range list to card
01588                         scanquad = CR_CHAN(chanlist[0]);        // get channel number;
01589                         gain = CR_RANGE(chanlist[0]);   // get gain number
01590                         scanquad |= ((gain & 0x03) << 8);
01591                         outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
01592                         DPRINTK("%02x ", scanquad | ssh);
01593                         ssh = devpriv->softsshhold;
01594                 }
01595                 DPRINTK("\n ");
01596         }
01597 
01598         DPRINTK("SL: ", ssh);
01599         for (i = 0; i < n_chan; i++) {  // store range list to card
01600                 scanquad = CR_CHAN(chanlist[i]);        // get channel number;
01601 #ifdef PCI9118_PARANOIDCHECK
01602                 devpriv->chanlist[i ^ usedma] = (scanquad & 0xf) << rot;
01603 #endif
01604                 gain = CR_RANGE(chanlist[i]);   // get gain number
01605                 scanquad |= ((gain & 0x03) << 8);
01606                 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
01607                 DPRINTK("%02x ", scanquad | ssh);
01608         }
01609         DPRINTK("\n ");
01610 
01611         if (backadd) {          // insert channels for fit onto 32bit DMA
01612                 DPRINTK("BA: %04x: ", ssh);
01613                 for (i = 0; i < backadd; i++) { // store range list to card
01614                         scanquad = CR_CHAN(chanlist[0]);        // get channel number;
01615                         gain = CR_RANGE(chanlist[0]);   // get gain number
01616                         scanquad |= ((gain & 0x03) << 8);
01617                         outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
01618                         DPRINTK("%02x ", scanquad | ssh);
01619                 }
01620                 DPRINTK("\n ");
01621         }
01622 #ifdef PCI9118_PARANOIDCHECK
01623         devpriv->chanlist[n_chan ^ usedma] = devpriv->chanlist[0 ^ usedma];     // for 32bit oerations
01624         if (useeos) {
01625                 for (i = 1; i < n_chan; i++) {  // store range list to card
01626                         devpriv->chanlist[(n_chan + i) ^ usedma] =
01627                                 (CR_CHAN(chanlist[i]) & 0xf) << rot;
01628                 }
01629                 devpriv->chanlist[(2 * n_chan) ^ usedma] = devpriv->chanlist[0 ^ usedma];       // for 32bit oerations
01630                 useeos = 2;
01631         } else {
01632                 useeos = 1;
01633         }
01634 #ifdef PCI9118_EXTDEBUG
01635         DPRINTK("CHL: ");
01636         for (i = 0; i <= (useeos * n_chan); i++) {
01637                 DPRINTK("%04x ", devpriv->chanlist[i]);
01638         }
01639         DPRINTK("\n ");
01640 #endif
01641 #endif
01642         outl(0, dev->iobase + PCI9118_SCANMOD); // close scan queue
01643 //      comedi_udelay(100);                             // important delay, or first sample will be cripled
01644 
01645         DPRINTK("adl_pci9118 EDBG: END: setup_channel_list()\n");
01646         return 1;               // we can serve this with scan logic
01647 }
01648 
01649 /*
01650 ==============================================================================
01651   calculate 8254 divisors if they are used for dual timing
01652 */
01653 static void pci9118_calc_divisors(char mode, comedi_device * dev,
01654         comedi_subdevice * s, unsigned int *tim1, unsigned int *tim2,
01655         unsigned int flags, int chans, unsigned int *div1, unsigned int *div2,
01656         char usessh, unsigned int chnsshfront)
01657 {
01658         DPRINTK("adl_pci9118 EDBG: BGN: pci9118_calc_divisors(%d,%d,.,%u,%u,%u,%d,.,.,,%u,%u)\n", mode, dev->minor, *tim1, *tim2, flags, chans, usessh, chnsshfront);
01659         switch (mode) {
01660         case 1:
01661         case 4:
01662                 if (*tim2 < this_board->ai_ns_min)
01663                         *tim2 = this_board->ai_ns_min;
01664                 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, div1, div2,
01665                         tim2, flags & TRIG_ROUND_NEAREST);
01666                 DPRINTK("OSC base=%u div1=%u div2=%u timer1=%u\n",
01667                         devpriv->i8254_osc_base, *div1, *div2, *tim1);
01668                 break;
01669         case 2:
01670                 if (*tim2 < this_board->ai_ns_min)
01671                         *tim2 = this_board->ai_ns_min;
01672                 DPRINTK("1 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
01673                         *tim1, *tim2);
01674                 *div1 = *tim2 / devpriv->i8254_osc_base;        // convert timer (burst)
01675                 DPRINTK("2 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
01676                         *tim1, *tim2);
01677                 if (*div1 < this_board->ai_pacer_min)
01678                         *div1 = this_board->ai_pacer_min;
01679                 DPRINTK("3 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
01680                         *tim1, *tim2);
01681                 *div2 = *tim1 / devpriv->i8254_osc_base;        // scan timer
01682                 DPRINTK("4 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
01683                         *tim1, *tim2);
01684                 *div2 = *div2 / *div1;  // major timer is c1*c2
01685                 DPRINTK("5 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
01686                         *tim1, *tim2);
01687                 if (*div2 < chans)
01688                         *div2 = chans;
01689                 DPRINTK("6 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
01690                         *tim1, *tim2);
01691 
01692                 *tim2 = *div1 * devpriv->i8254_osc_base;        // real convert timer
01693 
01694                 if (usessh & (chnsshfront == 0))        // use BSSH signal
01695                         if (*div2 < (chans + 2))
01696                                 *div2 = chans + 2;
01697 
01698                 DPRINTK("7 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
01699                         *tim1, *tim2);
01700                 *tim1 = *div1 * *div2 * devpriv->i8254_osc_base;
01701                 DPRINTK("OSC base=%u div1=%u div2=%u timer1=%u timer2=%u\n",
01702                         devpriv->i8254_osc_base, *div1, *div2, *tim1, *tim2);
01703                 break;
01704         }
01705         DPRINTK("adl_pci9118 EDBG: END: pci9118_calc_divisors(%u,%u)\n",
01706                 *div1, *div2);
01707 }
01708 
01709 /*
01710 ==============================================================================
01711 */
01712 static void start_pacer(comedi_device * dev, int mode, unsigned int divisor1,
01713         unsigned int divisor2)
01714 {
01715         outl(0x74, dev->iobase + PCI9118_CNTCTRL);
01716         outl(0xb4, dev->iobase + PCI9118_CNTCTRL);
01717 //      outl(0x30, dev->iobase + PCI9118_CNTCTRL);
01718         comedi_udelay(1);
01719 
01720         if ((mode == 1) || (mode == 2) || (mode == 4)) {
01721                 outl(divisor2 & 0xff, dev->iobase + PCI9118_CNT2);
01722                 outl((divisor2 >> 8) & 0xff, dev->iobase + PCI9118_CNT2);
01723                 outl(divisor1 & 0xff, dev->iobase + PCI9118_CNT1);
01724                 outl((divisor1 >> 8) & 0xff, dev->iobase + PCI9118_CNT1);
01725         }
01726 }
01727 
01728 /*
01729 ==============================================================================
01730 */
01731 static int pci9118_exttrg_add(comedi_device * dev, unsigned char source)
01732 {
01733         if (source > 3)
01734                 return -1;      // incorrect source
01735         devpriv->exttrg_users |= (1 << source);
01736         devpriv->IntControlReg |= Int_DTrg;
01737         outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
01738         outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00, devpriv->iobase_a + AMCC_OP_REG_INTCSR);     // allow INT in AMCC
01739         return 0;
01740 }
01741 
01742 /*
01743 ==============================================================================
01744 */
01745 static int pci9118_exttrg_del(comedi_device * dev, unsigned char source)
01746 {
01747         if (source > 3)
01748                 return -1;      // incorrect source
01749         devpriv->exttrg_users &= ~(1 << source);
01750         if (!devpriv->exttrg_users) {   // shutdown ext trg intterrupts
01751                 devpriv->IntControlReg &= ~Int_DTrg;
01752                 if (!devpriv->IntControlReg)    // all IRQ disabled
01753                         outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) & (~0x00001f00), devpriv->iobase_a + AMCC_OP_REG_INTCSR);      // disable int in AMCC
01754                 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
01755         }
01756         return 0;
01757 }
01758 
01759 /*
01760 ==============================================================================
01761 */
01762 static int pci9118_ai_cancel(comedi_device * dev, comedi_subdevice * s)
01763 {
01764         if (devpriv->usedma)
01765                 outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) & (~EN_A2P_TRANSFERS), devpriv->iobase_a + AMCC_OP_REG_MCSR);    // stop DMA
01766         pci9118_exttrg_del(dev, EXTTRG_AI);
01767         start_pacer(dev, 0, 0, 0);      // stop 8254 counters
01768         devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
01769         outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);     // positive triggers, no S&H, no burst, burst stop, no post trigger, no about trigger, trigger stop
01770         devpriv->AdControlReg = 0x00;
01771         outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);     // bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable INT and DMA
01772         outl(0, dev->iobase + PCI9118_BURST);
01773         outl(1, dev->iobase + PCI9118_SCANMOD);
01774         outl(2, dev->iobase + PCI9118_SCANMOD); // reset scan queue
01775         outl(0, dev->iobase + PCI9118_DELFIFO); // flush FIFO
01776 
01777         devpriv->ai_do = 0;
01778         devpriv->usedma = 0;
01779 
01780         devpriv->ai_act_scan = 0;
01781         devpriv->ai_act_dmapos = 0;
01782         s->async->cur_chan = 0;
01783         s->async->inttrig = NULL;
01784         devpriv->ai_buf_ptr = 0;
01785         devpriv->ai_neverending = 0;
01786         devpriv->dma_actbuf = 0;
01787 
01788         if (!devpriv->IntControlReg)
01789                 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00, devpriv->iobase_a + AMCC_OP_REG_INTCSR);     // allow INT in AMCC
01790 
01791         return 0;
01792 }
01793 
01794 /*
01795 ==============================================================================
01796 */
01797 static int pci9118_reset(comedi_device * dev)
01798 {
01799         devpriv->IntControlReg = 0;
01800         devpriv->exttrg_users = 0;
01801         inl(dev->iobase + PCI9118_INTCTRL);
01802         outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);    // disable interrupts source
01803         outl(0x30, dev->iobase + PCI9118_CNTCTRL);
01804 //        outl(0xb4, dev->iobase + PCI9118_CNTCTRL);
01805         start_pacer(dev, 0, 0, 0);      // stop 8254 counters
01806         devpriv->AdControlReg = 0;
01807         outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);     // bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable INT and DMA
01808         outl(0, dev->iobase + PCI9118_BURST);
01809         outl(1, dev->iobase + PCI9118_SCANMOD);
01810         outl(2, dev->iobase + PCI9118_SCANMOD); // reset scan queue
01811         devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
01812         outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);     // positive triggers, no S&H, no burst, burst stop, no post trigger, no about trigger, trigger stop
01813 
01814         devpriv->ao_data[0] = 2047;
01815         devpriv->ao_data[1] = 2047;
01816         outl(devpriv->ao_data[0], dev->iobase + PCI9118_DA1);   // reset A/D outs to 0V
01817         outl(devpriv->ao_data[1], dev->iobase + PCI9118_DA2);
01818         outl(0, dev->iobase + PCI9118_DO);      // reset digi outs to L
01819         comedi_udelay(10);
01820         inl(dev->iobase + PCI9118_AD_DATA);
01821         outl(0, dev->iobase + PCI9118_DELFIFO); // flush FIFO
01822         outl(0, dev->iobase + PCI9118_INTSRC);  // remove INT requests
01823         inl(dev->iobase + PCI9118_ADSTAT);      // flush A/D status register
01824         inl(dev->iobase + PCI9118_INTSRC);      // flush INT requests
01825         devpriv->AdControlReg = 0;
01826         outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);     // bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable INT and DMA
01827 
01828         devpriv->cnt0_users = 0;
01829         devpriv->exttrg_users = 0;
01830 
01831         return 0;
01832 }
01833 
01834 /*
01835 ==============================================================================
01836 */
01837 static int pci9118_attach(comedi_device * dev, comedi_devconfig * it)
01838 {
01839         comedi_subdevice *s;
01840         int ret, pages, i;
01841         unsigned short master;
01842         unsigned int irq;
01843         unsigned long iobase_a, iobase_9;
01844         struct pci_dev *pcidev;
01845         int opt_bus, opt_slot;
01846         const char *errstr;
01847         unsigned char pci_bus, pci_slot, pci_func;
01848         u16 u16w;
01849 
01850         rt_printk("comedi%d: adl_pci9118: board=%s", dev->minor,
01851                 this_board->name);
01852 
01853         opt_bus = it->options[0];
01854         opt_slot = it->options[1];
01855         if (it->options[3] & 1) {
01856                 master = 0;     // user don't want use bus master
01857         } else {
01858                 master = 1;
01859         }
01860 
01861         if ((ret = alloc_private(dev, sizeof(pci9118_private))) < 0) {
01862                 rt_printk(" - Allocation failed!\n");
01863                 return -ENOMEM;
01864         }
01865 
01866         /* Look for matching PCI device */
01867         errstr = "not found!";
01868         pcidev = NULL;
01869         while (NULL != (pcidev = pci_get_device(PCI_VENDOR_ID_AMCC,
01870                                 this_board->device_id, pcidev))) {
01871                 /* Found matching vendor/device. */
01872                 if (opt_bus || opt_slot) {
01873                         /* Check bus/slot. */
01874                         if (opt_bus != pcidev->bus->number
01875                                 || opt_slot != PCI_SLOT(pcidev->devfn))
01876                                 continue;       /* no match */
01877                 }
01878                 /*
01879                  * Look for device that isn't in use.
01880                  * Enable PCI device and request regions.
01881                  */
01882                 if (comedi_pci_enable(pcidev, "adl_pci9118")) {
01883                         errstr = "failed to enable PCI device and request regions!";
01884                         continue;
01885                 }
01886                 break;
01887         }
01888 
01889         if (!pcidev) {
01890                 if (opt_bus || opt_slot) {
01891                         rt_printk(" - Card at b:s %d:%d %s\n",
01892                                 opt_bus, opt_slot, errstr);
01893                 } else {
01894                         rt_printk(" - Card %s\n", errstr);
01895                 }
01896                 return -EIO;
01897         }
01898 
01899         if (master) {
01900                 pci_set_master(pcidev);
01901         }
01902 
01903         pci_bus = pcidev->bus->number;
01904         pci_slot = PCI_SLOT(pcidev->devfn);
01905         pci_func = PCI_FUNC(pcidev->devfn);
01906         irq = pcidev->irq;
01907         iobase_a = pci_resource_start(pcidev, 0);
01908         iobase_9 = pci_resource_start(pcidev, 2);
01909 
01910         rt_printk(", b:s:f=%d:%d:%d, io=0x%4lx, 0x%4lx", pci_bus, pci_slot,
01911                 pci_func, iobase_9, iobase_a);
01912 
01913         dev->iobase = iobase_9;
01914         dev->board_name = this_board->name;
01915 
01916         devpriv->pcidev = pcidev;
01917         devpriv->iobase_a = iobase_a;
01918 
01919         pci9118_reset(dev);
01920 
01921         if (it->options[3] & 2)
01922                 irq = 0;        // user don't want use IRQ
01923         if (irq > 0) {
01924                 if (comedi_request_irq(irq, interrupt_pci9118, IRQF_SHARED,
01925                                 "ADLink PCI-9118", dev)) {
01926                         rt_printk(", unable to allocate IRQ %d, DISABLING IT",
01927                                 irq);
01928                         irq = 0;        /* Can't use IRQ */
01929                 } else {
01930                         rt_printk(", irq=%u", irq);
01931                 }
01932         } else {
01933                 rt_printk(", IRQ disabled");
01934         }
01935 
01936         dev->irq = irq;
01937 
01938         if (master) {           // alloc DMA buffers
01939                 devpriv->dma_doublebuf = 0;
01940                 for (i = 0; i < 2; i++) {
01941                         for (pages = 4; pages >= 0; pages--)
01942                                 if ((devpriv->dmabuf_virt[i] = (sampl_t *)
01943                                                 __get_free_pages(GFP_KERNEL,
01944                                                         pages)))
01945                                         break;
01946                         if (devpriv->dmabuf_virt[i]) {
01947                                 devpriv->dmabuf_pages[i] = pages;
01948                                 devpriv->dmabuf_size[i] = PAGE_SIZE * pages;
01949                                 devpriv->dmabuf_samples[i] =
01950                                         devpriv->dmabuf_size[i] >> 1;
01951                                 devpriv->dmabuf_hw[i] =
01952                                         virt_to_bus((void *)devpriv->
01953                                         dmabuf_virt[i]);
01954                         }
01955                 }
01956                 if (!devpriv->dmabuf_virt[0]) {
01957                         rt_printk(", Can't allocate DMA buffer, DMA disabled!");
01958                         master = 0;
01959                 }
01960 
01961                 if (devpriv->dmabuf_virt[1])
01962                         devpriv->dma_doublebuf = 1;
01963 
01964         }
01965 
01966         if ((devpriv->master = master)) {
01967                 rt_printk(", bus master");
01968         } else {
01969                 rt_printk(", no bus master");
01970         }
01971 
01972         devpriv->usemux = 0;
01973         if (it->options[2] > 0) {
01974                 devpriv->usemux = it->options[2];
01975                 if (devpriv->usemux > 256)
01976                         devpriv->usemux = 256;  // max 256 channels!
01977                 if (it->options[4] > 0)
01978                         if (devpriv->usemux > 128) {
01979                                 devpriv->usemux = 128;  // max 128 channels with softare S&H!
01980                         }
01981                 rt_printk(", ext. mux %d channels", devpriv->usemux);
01982         }
01983 
01984         devpriv->softsshdelay = it->options[4];
01985         if (devpriv->softsshdelay < 0) {        // select sample&hold signal polarity
01986                 devpriv->softsshdelay = -devpriv->softsshdelay;
01987                 devpriv->softsshsample = 0x80;
01988                 devpriv->softsshhold = 0x00;
01989         } else {
01990                 devpriv->softsshsample = 0x00;
01991                 devpriv->softsshhold = 0x80;
01992         }
01993 
01994         rt_printk(".\n");
01995 
01996         pci_read_config_word(devpriv->pcidev, PCI_COMMAND, &u16w);
01997         pci_write_config_word(devpriv->pcidev, PCI_COMMAND, u16w | 64); // Enable parity check for parity error
01998 
01999         if ((ret = alloc_subdevices(dev, 4)) < 0)
02000                 return ret;
02001 
02002         s = dev->subdevices + 0;
02003         dev->read_subdev = s;
02004         s->type = COMEDI_SUBD_AI;
02005         s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
02006         if (devpriv->usemux) {
02007                 s->n_chan = devpriv->usemux;
02008         } else {
02009                 s->n_chan = this_board->n_aichan;
02010         }
02011         s->maxdata = this_board->ai_maxdata;
02012         s->len_chanlist = this_board->n_aichanlist;
02013         s->range_table = this_board->rangelist_ai;
02014         s->cancel = pci9118_ai_cancel;
02015         s->insn_read = pci9118_insn_read_ai;
02016         if (dev->irq) {
02017                 s->subdev_flags |= SDF_CMD_READ;
02018                 s->do_cmdtest = pci9118_ai_cmdtest;
02019                 s->do_cmd = pci9118_ai_cmd;
02020                 s->munge = pci9118_ai_munge;
02021         }
02022 
02023         s = dev->subdevices + 1;
02024         s->type = COMEDI_SUBD_AO;
02025         s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
02026         s->n_chan = this_board->n_aochan;
02027         s->maxdata = this_board->ao_maxdata;
02028         s->len_chanlist = this_board->n_aochan;
02029         s->range_table = this_board->rangelist_ao;
02030         s->insn_write = pci9118_insn_write_ao;
02031         s->insn_read = pci9118_insn_read_ao;
02032 
02033         s = dev->subdevices + 2;
02034         s->type = COMEDI_SUBD_DI;
02035         s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
02036         s->n_chan = 4;
02037         s->maxdata = 1;
02038         s->len_chanlist = 4;
02039         s->range_table = &range_digital;
02040         s->io_bits = 0;         /* all bits input */
02041         s->insn_bits = pci9118_insn_bits_di;
02042 
02043         s = dev->subdevices + 3;
02044         s->type = COMEDI_SUBD_DO;
02045         s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
02046         s->n_chan = 4;
02047         s->maxdata = 1;
02048         s->len_chanlist = 4;
02049         s->range_table = &range_digital;
02050         s->io_bits = 0xf;       /* all bits output */
02051         s->insn_bits = pci9118_insn_bits_do;
02052 
02053         devpriv->valid = 1;
02054         devpriv->i8254_osc_base = 250;  // 250ns=4MHz
02055         devpriv->ai_maskharderr = 0x10a;        // default measure crash condition
02056         if (it->options[5])     // disable some requested
02057                 devpriv->ai_maskharderr &= ~it->options[5];
02058 
02059         switch (this_board->ai_maxdata) {
02060         case 0xffff:
02061                 devpriv->ai16bits = 1;
02062                 break;
02063         default:
02064                 devpriv->ai16bits = 0;
02065                 break;
02066         }
02067         return 0;
02068 }
02069 
02070 /*
02071 ==============================================================================
02072 */
02073 static int pci9118_detach(comedi_device * dev)
02074 {
02075         if (dev->private) {
02076                 if (devpriv->valid)
02077                         pci9118_reset(dev);
02078                 if (dev->irq)
02079                         comedi_free_irq(dev->irq, dev);
02080                 if (devpriv->pcidev) {
02081                         if (dev->iobase) {
02082                                 comedi_pci_disable(devpriv->pcidev);
02083                         }
02084                         pci_dev_put(devpriv->pcidev);
02085                 }
02086                 if (devpriv->dmabuf_virt[0])
02087                         free_pages((unsigned long)devpriv->dmabuf_virt[0],
02088                                 devpriv->dmabuf_pages[0]);
02089                 if (devpriv->dmabuf_virt[1])
02090                         free_pages((unsigned long)devpriv->dmabuf_virt[1],
02091                                 devpriv->dmabuf_pages[1]);
02092         }
02093 
02094         return 0;
02095 }
02096 
02097 /*
02098 ==============================================================================
02099 */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines