From f3b96ff60064216b81c40c134150df6a1a2b8384 Mon Sep 17 00:00:00 2001 From: Frank Mori Hess Date: Tue, 18 Sep 2001 23:23:36 +0000 Subject: [PATCH] more pci-dma stuff, still nonfunctional --- comedi/drivers/cb_pcidas64.c | 94 ++++++++++++++++++++++++++++-------- comedi/drivers/plx9080.h | 41 ++++++++++------ 2 files changed, 99 insertions(+), 36 deletions(-) diff --git a/comedi/drivers/cb_pcidas64.c b/comedi/drivers/cb_pcidas64.c index cebd3020..4d8c74ed 100644 --- a/comedi/drivers/cb_pcidas64.c +++ b/comedi/drivers/cb_pcidas64.c @@ -96,7 +96,7 @@ TODO: #define PRESCALED_TIMER_BASE 10000 // 100kHz 'prescaled' clock for slow aquisition, maybe I'll support this someday #define QUARTER_AI_FIFO_SIZE 2048 // 1/4 analog input fifo size // size in bytes of transfers used for dma transfers, also size of buffers that make up dma ring -#define AI_DMA_TRANSFER_SIZE 0x4000 +#define DMA_TRANSFER_SIZE 0x4000 // number of dma transfers we will chain together into a ring (and the number of dma buffers we maintain) #define DMA_RING_COUNT 10 @@ -388,9 +388,12 @@ typedef struct unsigned long plx9080_iobase; unsigned long main_iobase; unsigned long dio_counter_iobase; + // local address (used by dma controller) + u32 local_main_iobase; volatile unsigned int ai_count; // number of analog input samples remaining u16 *ai_buffer[DMA_RING_COUNT]; // dma buffers for analog input dma_addr_t ai_buffer_phys_addr[DMA_RING_COUNT]; // physical addresses of ai dma buffers + struct plx_dma_desc *dma_desc; // array of dma descriptors read by plx9080, allocated to get proper alignment volatile unsigned int ao_count; // number of analog output samples remaining unsigned int ao_value[2]; // remember what the analog outputs are set to, to allow readback unsigned int hw_revision; // stc chip hardware revision number @@ -456,6 +459,10 @@ static int attach(comedi_device *dev, comedi_devconfig *it) unsigned long plx9080_iobase; unsigned long main_iobase; unsigned long dio_counter_iobase; + u32 local_range, local_decode; +#ifdef PCIDMA + unsigned int bits; +#endif printk("comedi%d: cb_pcidas64\n",dev->minor); @@ -572,6 +579,11 @@ found: devpriv->main_iobase = (unsigned long)ioremap(main_iobase, MAIN_IOSIZE); devpriv->dio_counter_iobase = (unsigned long)ioremap(dio_counter_iobase, DIO_COUNTER_IOSIZE); + // figure out what local address is for main_iobase + local_range = readl(devpriv->plx9080_iobase + PLX_LAS0RNG_REG) & LRNG_MEM_MASK; + local_decode = readl(devpriv->plx9080_iobase + PLX_LAS0MAP_REG) & local_range & LMAP_MEM_MASK ; + devpriv->local_main_iobase = (devpriv->main_phys_iobase & ~local_range) | local_decode; + devpriv->hw_revision = HW_REVISION(readw(devpriv->main_iobase + HW_STATUS_REG)); // get irq @@ -582,15 +594,6 @@ found: } dev->irq = pcidev->irq; -#ifdef PCIDMA - // alocate pci dma buffers - for(index = 0; index < DMA_RING_COUNT; i++) - { - devpriv->ai_buffer[index] = - pci_alloc_consistent(devpriv->hw_dev, DMA_BUFFER_SIZE, &devpriv->ai_buffer_phys_addr[index]); - } -#endif - #ifdef PCIDAS64_DEBUG printk(" plx9080 phys io addr 0x%lx\n", devpriv->plx9080_phys_iobase); @@ -603,6 +606,8 @@ printk(" main virt io addr 0x%lx\n", devpriv->main_iobase); printk(" diocounter virt io addr 0x%lx\n", devpriv->dio_counter_iobase); printk(" irq %i\n", dev->irq); +printk(" local main io addr 0x%ulx\n", devpriv->local_main_iobase); + printk(" stc hardware revision %i\n", devpriv->hw_revision); // plx9080 dump @@ -619,6 +624,43 @@ printk(" plx dma channel 0 threshold 0x%x\n", readl(devpriv->plx9080_iobase + PL #endif +#ifdef PCIDMA + // alocate pci dma buffers + for(index = 0; index < DMA_RING_COUNT; index++) + { + devpriv->ai_buffer[index] = + pci_alloc_consistent(devpriv->hw_dev, DMA_TRANSFER_SIZE, &devpriv->ai_buffer_phys_addr[index]); + } + // allocate dma descriptors + devpriv->dma_desc = kmalloc(sizeof(struct plx_dma_desc) * DMA_RING_COUNT, GFP_KERNEL); + // initialize dma descriptors + for(index = 0; index < DMA_RING_COUNT; index++) + { + devpriv->dma_desc[index].pci_start_addr = virt_to_bus(devpriv->ai_buffer[index]); + devpriv->dma_desc[index].local_start_addr = devpriv->local_main_iobase + ADC_FIFO_REG; + devpriv->dma_desc[index].transfer_size = DMA_TRANSFER_SIZE; + devpriv->dma_desc[index].next = virt_to_bus(&devpriv->dma_desc[(index + 1) % (DMA_RING_COUNT)]) | + PLX_DESC_IN_PCI_BIT | PLX_INTR_TERM_COUNT | PLX_XFER_LOCAL_TO_PCI; + } + // do some initialization of plx9080 dma registers + /* XXX there are some other bits that can be set here that might + * improve performance, but I just want to get it working */ + bits = 0; + // localspace0 bus is 16 bits wide + bits |= PLX_LOCAL_BUS_16_WIDE_BITS; + // enable ready input, not sure if this is necessary + bits |= PLX_DMA_EN_READYIN_BIT; + // enable dma chaining + bits |= PLX_EN_CHAIN_BIT; + // enable interrupt on dma done (probably don't need this, since chain never finishes) + bits |= PLX_EN_DMA_DONE_INTR_BIT; + // don't increment local address during transfers (we are transferring from a fixed fifo register) + bits |= PLX_LOCAL_ADDR_CONST_BIT; + // route dma interrupt to pci bus + bits |= PLX_DMA_INTR_PCI_BIT; + writel(bits, devpriv->plx9080_iobase + PLX_DMA0_MODE_REG); + +#endif /* * Allocate the subdevice structures. @@ -737,6 +779,8 @@ static int detach(comedi_device *dev) pci_free_consistent(devpriv->hw_dev, DMA_BUFFER_SIZE, devpriv->ai_buffer[i], devpriv->ai_buffer_phys_addr[i]); } + // free dma descriptors + kfree(devpriv->dma_desc); #endif } if(dev->irq) @@ -958,7 +1002,7 @@ static int ai_cmd(comedi_device *dev,comedi_subdevice *s) { comedi_async *async = s->async; comedi_cmd *cmd = &async->cmd; - unsigned int bits; + u32 bits; unsigned int convert_counter_value; unsigned int scan_counter_value; unsigned int i; @@ -1041,6 +1085,19 @@ static int ai_cmd(comedi_device *dev,comedi_subdevice *s) // clear adc buffer writew(0, devpriv->main_iobase + ADC_BUFFER_CLEAR_REG); +#ifdef PCIDMA + // give location of first dma descriptor + bits = virt_to_bus(devpriv->dma_desc); + bits |= PLX_DESC_IN_PCI_BIT | PLX_INTR_TERM_COUNT | PLX_XFER_LOCAL_TO_PCI; + writel(bits, devpriv->plx9080_iobase + PLX_DMA0_DESCRIPTOR_REG); + // enable dma transfer + writeb(PLX_DMA_EN_BIT | PLX_DMA_START_BIT, devpriv->plx9080_iobase + PLX_DMA0_CS_REG); + writeb(0, devpriv->plx9080_iobase + PLX_DMA1_CS_REG); +#else + writeb(0, devpriv->plx9080_iobase + PLX_DMA0_CS_REG); + writeb(0, devpriv->plx9080_iobase + PLX_DMA1_CS_REG); +#endif + // enable interrupts devpriv->intr_enable_bits |= EN_ADC_OVERRUN_BIT | EN_ADC_DONE_INTR_BIT; if(cmd->stop_src == TRIG_EXT) @@ -1050,17 +1107,11 @@ static int ai_cmd(comedi_device *dev,comedi_subdevice *s) else devpriv->intr_enable_bits |= ADC_INTR_QFULL_BITS; // for clairity only, since quarter-full bits are zero writew(devpriv->intr_enable_bits, devpriv->main_iobase + INTR_ENABLE_REG); - // enable interrupts on plx 9080 XXX enabling more interrupt sources than are actually used - bits = ICS_PIE | ICS_PLIE | ICS_PAIE | ICS_PDIE | ICS_LIE | ICS_LDIE | ICS_DMA0_E | ICS_DMA1_E; + // enable interrupts on plx 9080 + // XXX enabling more interrupt sources than are actually used + bits = ICS_PIE | ICS_PLIE | ICS_PAIE | ICS_PDIE | ICS_LIE | ICS_LDIE | ICS_DMA0_E | ICS_DMA1_E | ICS_MBIE; writel(bits, devpriv->plx9080_iobase + PLX_INTRCS_REG); -#ifdef PCIDMA -//XXX -#else - writeb(0, devpriv->plx9080_iobase + PLX_DMA0_CS_REG); - writeb(0, devpriv->plx9080_iobase + PLX_DMA1_CS_REG); -#endif - /* set mode, disable software conversion gate */ bits = ADC_CONTROL1_DUMMY_BITS | SW_NOGATE_BIT; if(cmd->convert_src == TRIG_EXT) @@ -1106,7 +1157,8 @@ static void handle_interrupt(int irq, void *d, struct pt_regs *regs) if((status & (ADC_INTR_PENDING_BIT | ADC_DONE_BIT | ADC_STOP_BIT | DAC_INTR_PENDING_BIT | DAC_DONE_BIT | EXT_INTR_PENDING_BIT)) == 0 && - (plx_status & (ICS_DMA0_A | ICS_DMA1_A | ICS_LDIA | ICS_LIA | ICS_PAIA | ICS_PDIA)) == 0) + (plx_status & (ICS_DMA0_A | ICS_DMA1_A | ICS_LDIA | ICS_LIA | ICS_PAIA | ICS_PDIA | + ICS_MBIA(0) | ICS_MBIA(1) |ICS_MBIA(2) | ICS_MBIA(3))) == 0) { #ifdef PCIDAS64_DEBUG intr_count++; diff --git a/comedi/drivers/plx9080.h b/comedi/drivers/plx9080.h index 3e0be5b2..814e653c 100644 --- a/comedi/drivers/plx9080.h +++ b/comedi/drivers/plx9080.h @@ -45,16 +45,18 @@ struct plx_dma_desc ** **********************************************************************/ -#define PLX_LASMAP_REG 0x0000 /* L, Local Addr Space Range Register */ -#define LASMAP_IO 0x00000001 /* Map to: 1=I/O, 0=Mem */ -#define LMAP_ANY32 0x00000000 /* Locate anywhere in 32 bit */ -#define LMAP_LT1MB 0x00000002 /* Locate in 1st meg */ -#define LMAP_ANY64 0x00000004 /* Locate anywhere in 64 bit */ +#define PLX_LAS0RNG_REG 0x0000 /* L, Local Addr Space 0 Range Register */ +#define LRNG_IO 0x00000001 /* Map to: 1=I/O, 0=Mem */ +#define LRNG_ANY32 0x00000000 /* Locate anywhere in 32 bit */ +#define LRNG_LT1MB 0x00000002 /* Locate in 1st meg */ +#define LRNG_ANY64 0x00000004 /* Locate anywhere in 64 bit */ +#define LRNG_MEM_MASK 0xfffffff0 // bits that specify range for memory io +#define LRNG_IO_MASK 0xfffffffa // bits that specify range for normal io -#define PLX_LASRNG_REG 0x0004 /* L, Local Addr Space Range Register */ -#define LRNG_EN 0x00000001 /* Enable slave decode */ -#define LRNG_IO 0xFFFFFFFC /* Decode bits if I/O spc */ -#define LRNG_MEM 0xFFFFFFF0 /* Decode bits if mem spc */ +#define PLX_LAS0MAP_REG 0x0004 /* L, Local Addr Space 0 Remap Register */ +#define LMAP_EN 0x00000001 /* Enable slave decode */ +#define LMAP_MEM_MASK 0xfffffff0 // bits that specify decode for memory io +#define LMAP_IO_MASK 0xfffffffa // bits that specify decode bits for normal io /* Note: The Local Arbitration Register is only present on the 9060ES part. @@ -139,6 +141,7 @@ struct plx_dma_desc #define ICS_AERR 0x00000001 /* Assert LSERR on ABORT */ #define ICS_PERR 0x00000002 /* Assert LSERR on Parity Error */ #define ICS_SERR 0x00000004 /* Generate PCI SERR# */ +#define ICS_MBIE 0x00000008 // mailbox interrupt enable #define ICS_PIE 0x00000100 /* PCI Interrupt Enable */ #define ICS_PDIE 0x00000200 /* PCI Doorbell Interrupt Enable */ #define ICS_PAIE 0x00000400 /* PCI Abort Interrupt Enable */ @@ -159,6 +162,7 @@ struct plx_dma_desc #define ICS_TA_DMA0 0x02000000 /* Target Abort - DMA #0 */ #define ICS_TA_DMA1 0x04000000 /* Target Abort - DMA #1 */ #define ICS_TA_RA 0x08000000 /* Target Abort - Retry Timeout */ +#define ICS_MBIA(x) (0x10000000 << ((x) & 0x3)) // mailbox x is active #define PLX_CONTROL_REG 0x006C /* L, EEPROM Cntl & PCI Cmd Codes */ #define CTL_RDMA 0x0000000F /* DMA Read Command */ @@ -181,6 +185,13 @@ struct plx_dma_desc #define PLX_REVISION_REG 0x74 // silicon revision #define PLX_DMA0_MODE_REG 0x80 // dma channel 0 mode register +#define PLX_LOCAL_BUS_16_WIDE_BITS 0x1 +#define PLX_LOCAL_BUS_WIDTH_MASK 0x3 +#define PLX_DMA_EN_READYIN_BIT 0x40 // enable ready in input +#define PLX_EN_CHAIN_BIT 0x200 // enables chaining +#define PLX_EN_DMA_DONE_INTR_BIT 0x400 // enables interrupt on dma done +#define PLX_LOCAL_ADDR_CONST_BIT 0x800 // hold local address constant (don't increment) +#define PLX_DMA_INTR_PCI_BIT 0x20000 // routes dma interrupt to pci bus (instead of local bus) #define PLX_DMA0_PCI_ADDRESS_REG 0x84 // pci address that dma transfers start at @@ -190,15 +201,15 @@ struct plx_dma_desc #define PLX_DMA0_DESCRIPTOR_REG 0x90 // descriptor pointer register #define PLX_DMA1_DESCRIPTOR_REG 0xa4 -#define PLX_LOCAL_BUS_16_WIDE_BITS 0x1 -#define PLX_LOCAL_BUS_WIDTH_MASK 0x3 -#define PLX_EN_CHAIN_BIT 0x200 // enables chaining -#define PLX_EN_DMA_DONE_INTR_BIT 0x400 // enables interrupt on dma done -#define PLX_LOCAL_ADDR_CONST_BIT 0x800 // hold local address constant (don't increment) -#define PLX_DMA_INTR_PCI_BIT 0x20000 // routes dma interrupt to pci bus (instead of local bus) +#define PLX_DESC_IN_PCI_BIT 0x1 // descriptor is located in pci space (not local space) +#define PLX_END_OF_CHAIN_BIT 0x2 // end of chain bit +#define PLX_INTR_TERM_COUNT 0x4 // interrupt when this descriptor's transfer is finished +#define PLX_XFER_LOCAL_TO_PCI 0x8 // transfer from local to pci bus (not pci to local) #define PLX_DMA0_CS_REG 0xa8 // command status register #define PLX_DMA1_CS_REG 0xa9 +#define PLX_DMA_EN_BIT 0x1 // enable dma channel +#define PLX_DMA_START_BIT 0x2 // start dma transfer #define PLX_CLEAR_DMA_INTR_BIT 0x8 #define PLX_DMA0_THRESHOLD_REG 0xb0 // command status register -- 2.26.2