From: H Hartley Sweeten Date: Tue, 4 Nov 2014 17:54:46 +0000 (-0700) Subject: staging: comedi: addi_apci_3120: factor DMA setup out of apci3120_cyclic_ai() X-Git-Tag: v3.19-rc1~66^2~293 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=e451dfeb4c205f74b3bfc35d58fd1a17dff490ed;p=karo-tx-linux.git staging: comedi: addi_apci_3120: factor DMA setup out of apci3120_cyclic_ai() For aesthetics, factor the DMA setup code out of apci3120_cyclic_ai(). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c index f7543f684016..6377c37fde16 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c @@ -224,6 +224,153 @@ static int apci3120_ai_cmdtest(struct comedi_device *dev, return 0; } +static void apci3120_setup_dma(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + struct apci3120_private *devpriv = dev->private; + struct comedi_cmd *cmd = &s->async->cmd; + struct apci3120_dmabuf *dmabuf0 = &devpriv->dmabuf[0]; + struct apci3120_dmabuf *dmabuf1 = &devpriv->dmabuf[1]; + unsigned int dmalen0 = dmabuf0->size; + unsigned int dmalen1 = dmabuf1->size; + unsigned int scan_bytes; + + scan_bytes = comedi_samples_to_bytes(s, cmd->scan_end_arg); + + if (cmd->stop_src == TRIG_COUNT) { + /* + * Must we fill full first buffer? And must we fill + * full second buffer when first is once filled? + */ + if (dmalen0 > (cmd->stop_arg * scan_bytes)) + dmalen0 = cmd->stop_arg * scan_bytes; + else if (dmalen1 > (cmd->stop_arg * scan_bytes - dmalen0)) + dmalen1 = cmd->stop_arg * scan_bytes - dmalen0; + } + + if (cmd->flags & CMDF_WAKE_EOS) { + /* don't we want wake up every scan? */ + if (dmalen0 > scan_bytes) { + dmalen0 = scan_bytes; + if (cmd->scan_end_arg & 1) + dmalen0 += 2; + } + if (dmalen1 > scan_bytes) { + dmalen1 = scan_bytes; + if (cmd->scan_end_arg & 1) + dmalen1 -= 2; + if (dmalen1 < 4) + dmalen1 = 4; + } + } else { + /* isn't output buff smaller that our DMA buff? */ + if (dmalen0 > s->async->prealloc_bufsz) + dmalen0 = s->async->prealloc_bufsz; + if (dmalen1 > s->async->prealloc_bufsz) + dmalen1 = s->async->prealloc_bufsz; + } + dmabuf0->use_size = dmalen0; + dmabuf1->use_size = dmalen1; + + /* Initialize DMA */ + + /* + * Set Transfer count enable bit and A2P_fifo reset bit in AGCSTS + * register 1 + */ + outl(AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO, + devpriv->amcc + AMCC_OP_REG_AGCSTS); + + /* changed since 16 bit interface for add on */ + /* ENABLE BUS MASTER */ + outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->addon + 0); + outw(APCI3120_ENABLE_TRANSFER_ADD_ON_LOW, devpriv->addon + 2); + + outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->addon + 0); + outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH, devpriv->addon + 2); + + /* + * TO VERIFIED BEGIN JK 07.05.04: Comparison between WIN32 and Linux + * driver + */ + outw(0x1000, devpriv->addon + 2); + /* END JK 07.05.04: Comparison between WIN32 and Linux driver */ + + /* 2 No change */ + /* A2P FIFO MANAGEMENT */ + /* A2P fifo reset & transfer control enable */ + outl(APCI3120_A2P_FIFO_MANAGEMENT, + devpriv->amcc + APCI3120_AMCC_OP_MCSR); + + /* + * 3 + * beginning address of dma buf The 32 bit address of dma buffer + * is converted into two 16 bit addresses Can done by using _attach + * and put into into an array array used may be for differnet pages + */ + + /* DMA Start Address Low */ + outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->addon + 0); + outw(dmabuf0->hw & 0xffff, devpriv->addon + 2); + + /* DMA Start Address High */ + outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->addon + 0); + outw((dmabuf0->hw >> 16) & 0xffff, devpriv->addon + 2); + + /* + * 4 + * amount of bytes to be transferred set transfer count used ADDON + * MWTC register commented testing + */ + + /* Nbr of acquisition LOW */ + outw(APCI3120_ADD_ON_MWTC_LOW, devpriv->addon + 0); + outw(dmabuf0->use_size & 0xffff, devpriv->addon + 2); + + /* Nbr of acquisition HIGH */ + outw(APCI3120_ADD_ON_MWTC_HIGH, devpriv->addon + 0); + outw((dmabuf0->use_size >> 16) & 0xffff, devpriv->addon + 2); + + /* + * 5 + * To configure A2P FIFO testing outl( + * FIFO_ADVANCE_ON_BYTE_2, devpriv->amcc + AMCC_OP_REG_INTCSR); + */ + + /* A2P FIFO RESET */ + /* + * TO VERIFY BEGIN JK 07.05.04: Comparison between WIN32 and Linux + * driver + */ + outl(0x04000000UL, devpriv->amcc + AMCC_OP_REG_MCSR); + /* END JK 07.05.04: Comparison between WIN32 and Linux driver */ + + /* + * 6 + * ENABLE A2P FIFO WRITE AND ENABLE AMWEN AMWEN_ENABLE | + * A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03 + */ + + /* + * 7 + * initialise end of dma interrupt AINT_WRITE_COMPL = + * ENABLE_WRITE_TC_INT(ADDI) + */ + /* A2P FIFO CONFIGURATE, END OF DMA intERRUPT INIT */ + outl(APCI3120_FIFO_ADVANCE_ON_BYTE_2 | APCI3120_ENABLE_WRITE_TC_INT, + devpriv->amcc + AMCC_OP_REG_INTCSR); + + /* BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver */ + /* ENABLE A2P FIFO WRITE AND ENABLE AMWEN */ + outw(3, devpriv->addon + 4); + /* END JK 07.05.04: Comparison between WIN32 and Linux driver */ + + /* A2P FIFO RESET */ + /* BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver */ + outl(0x04000000UL, devpriv->amcc + APCI3120_AMCC_OP_MCSR); + /* END JK 07.05.04: Comparison between WIN32 and Linux driver */ +} + /* * This is used for analog input cyclic acquisition. * Performs the command operations. @@ -237,8 +384,6 @@ static int apci3120_cyclic_ai(int mode, struct apci3120_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; unsigned int divisor1 = 0; - unsigned int dmalen0 = 0; - unsigned int dmalen1 = 0; unsigned int divisor0; /* clear software registers */ @@ -320,152 +465,8 @@ static int apci3120_cyclic_ai(int mode, devpriv->b_Timer2Interrupt = APCI3120_ENABLE; } } else { - /* If DMA Enabled */ - struct apci3120_dmabuf *dmabuf0 = &devpriv->dmabuf[0]; - struct apci3120_dmabuf *dmabuf1 = &devpriv->dmabuf[1]; - unsigned int scan_bytes; - - scan_bytes = comedi_samples_to_bytes(s, cmd->scan_end_arg); - devpriv->b_InterruptMode = APCI3120_DMA_MODE; - - dmalen0 = dmabuf0->size; - dmalen1 = dmabuf1->size; - - if (cmd->stop_src == TRIG_COUNT) { - /* - * Must we fill full first buffer? And must we fill - * full second buffer when first is once filled? - */ - if (dmalen0 > (cmd->stop_arg * scan_bytes)) { - dmalen0 = cmd->stop_arg * scan_bytes; - } else if (dmalen1 > (cmd->stop_arg * scan_bytes - - dmalen0)) - dmalen1 = cmd->stop_arg * scan_bytes - - dmalen0; - } - - if (cmd->flags & CMDF_WAKE_EOS) { - /* don't we want wake up every scan? */ - if (dmalen0 > scan_bytes) { - dmalen0 = scan_bytes; - if (cmd->scan_end_arg & 1) - dmalen0 += 2; - } - if (dmalen1 > scan_bytes) { - dmalen1 = scan_bytes; - if (cmd->scan_end_arg & 1) - dmalen1 -= 2; - if (dmalen1 < 4) - dmalen1 = 4; - } - } else { /* isn't output buff smaller that our DMA buff? */ - if (dmalen0 > s->async->prealloc_bufsz) - dmalen0 = s->async->prealloc_bufsz; - if (dmalen1 > s->async->prealloc_bufsz) - dmalen1 = s->async->prealloc_bufsz; - } - dmabuf0->use_size = dmalen0; - dmabuf1->use_size = dmalen1; - - /* Initialize DMA */ - - /* - * Set Transfer count enable bit and A2P_fifo reset bit in AGCSTS - * register 1 - */ - outl(AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO, - devpriv->amcc + AMCC_OP_REG_AGCSTS); - - /* changed since 16 bit interface for add on */ - /* ENABLE BUS MASTER */ - outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->addon + 0); - outw(APCI3120_ENABLE_TRANSFER_ADD_ON_LOW, devpriv->addon + 2); - - outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->addon + 0); - outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH, devpriv->addon + 2); - - /* - * TO VERIFIED BEGIN JK 07.05.04: Comparison between WIN32 and Linux - * driver - */ - outw(0x1000, devpriv->addon + 2); - /* END JK 07.05.04: Comparison between WIN32 and Linux driver */ - - /* 2 No change */ - /* A2P FIFO MANAGEMENT */ - /* A2P fifo reset & transfer control enable */ - outl(APCI3120_A2P_FIFO_MANAGEMENT, - devpriv->amcc + APCI3120_AMCC_OP_MCSR); - - /* - * 3 - * beginning address of dma buf The 32 bit address of dma buffer - * is converted into two 16 bit addresses Can done by using _attach - * and put into into an array array used may be for differnet pages - */ - - /* DMA Start Address Low */ - outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->addon + 0); - outw(dmabuf0->hw & 0xffff, devpriv->addon + 2); - - /* DMA Start Address High */ - outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->addon + 0); - outw((dmabuf0->hw >> 16) & 0xffff, devpriv->addon + 2); - - /* - * 4 - * amount of bytes to be transferred set transfer count used ADDON - * MWTC register commented testing - */ - - /* Nbr of acquisition LOW */ - outw(APCI3120_ADD_ON_MWTC_LOW, devpriv->addon + 0); - outw(dmabuf0->use_size & 0xffff, devpriv->addon + 2); - - /* Nbr of acquisition HIGH */ - outw(APCI3120_ADD_ON_MWTC_HIGH, devpriv->addon + 0); - outw((dmabuf0->use_size >> 16) & 0xffff, devpriv->addon + 2); - - /* - * 5 - * To configure A2P FIFO testing outl( - * FIFO_ADVANCE_ON_BYTE_2, devpriv->amcc + AMCC_OP_REG_INTCSR); - */ - - /* A2P FIFO RESET */ - /* - * TO VERIFY BEGIN JK 07.05.04: Comparison between WIN32 and Linux - * driver - */ - outl(0x04000000UL, devpriv->amcc + AMCC_OP_REG_MCSR); - /* END JK 07.05.04: Comparison between WIN32 and Linux driver */ - - /* - * 6 - * ENABLE A2P FIFO WRITE AND ENABLE AMWEN AMWEN_ENABLE | - * A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03 - */ - - /* - * 7 - * initialise end of dma interrupt AINT_WRITE_COMPL = - * ENABLE_WRITE_TC_INT(ADDI) - */ - /* A2P FIFO CONFIGURATE, END OF DMA intERRUPT INIT */ - outl((APCI3120_FIFO_ADVANCE_ON_BYTE_2 | - APCI3120_ENABLE_WRITE_TC_INT), - devpriv->amcc + AMCC_OP_REG_INTCSR); - - /* BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver */ - /* ENABLE A2P FIFO WRITE AND ENABLE AMWEN */ - outw(3, devpriv->addon + 4); - /* END JK 07.05.04: Comparison between WIN32 and Linux driver */ - - /* A2P FIFO RESET */ - /* BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver */ - outl(0x04000000UL, devpriv->amcc + APCI3120_AMCC_OP_MCSR); - /* END JK 07.05.04: Comparison between WIN32 and Linux driver */ + apci3120_setup_dma(dev, s); } if (devpriv->us_UseDma == APCI3120_DISABLE &&