/* -*-C-*-
*******************************************************************************
*
* File:         mc4020_util.h
* Description:  low level inline i/o primitives
*
*******************************************************************************
*/
/*
 * Copyright 2001 Free Software Foundation, Inc.
 * 
 * This file is part of GNU Radio
 * 
 * GNU Radio is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 * 
 * GNU Radio is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with GNU Radio; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */
#ifndef _MC4020_UTIL_H_
#define _MC4020_UTIL_H_

inline static void 
mc_write (struct mc4020 *mc, int offset, int value)
{
  if(shadowed_p (offset))
    mc->shadow[(offset - MIN_SHADOW) / sizeof (u16)] = value;

  writew (value, mc->reg_vaddr + offset);
}

inline static u16
mc_read (struct mc4020 *mc, int offset)
{
  return readw (mc->reg_vaddr + offset);
}

inline static u16
mc_read_shadow (struct mc4020 *mc, int offset)
{
  if (shadowed_p (offset))
    return mc->shadow[(offset - MIN_SHADOW) / sizeof (u16)];
      
#ifdef DEBUG
  printk (KERN_WARNING
	  "m4020: BUG mc_read_shadow of non-shadowed register (0x%x)\n", offset);
#endif

  return 0;
}

inline static void
mc_and (struct mc4020 *mc, int offset, int value)
{
  mc_write (mc, offset, value & mc_read_shadow (mc, offset));
}

inline static void
mc_or (struct mc4020 *mc, int offset, int value)
{
  mc_write (mc, offset, value | mc_read_shadow (mc, offset));
}

inline static void
mc_aor (struct mc4020 *mc, int offset, int value, int mask)
{
  mc_write (mc, offset, value | (mask & mc_read_shadow (mc, offset)));
}

inline static void
mc_and_cr0 (struct mc4020 *mc, int value)
{
  mc_and (mc, MC4020_DAQ_CR0_OFF, value);
}
inline static void
mc_and_cr1 (struct mc4020 *mc, int value)
{
  mc_and (mc, MC4020_DAQ_CR1_OFF, value);
}

inline static void
mc_or_cr0 (struct mc4020 *mc, int value)
{
  mc_or (mc, MC4020_DAQ_CR0_OFF, value);
}
inline static void
mc_or_cr1 (struct mc4020 *mc, int value)
{
  mc_or (mc, MC4020_DAQ_CR1_OFF, value);
}
/* --- write only regs --- */

inline static void
mc_write_intr_enable (struct mc4020 *mc, int value)
{
  mc_write (mc, MC4020_INTR_ENABLE_OFF, value);
}

inline static void
mc_write_hw_conf (struct mc4020 *mc, int value)
{
  mc_write (mc, MC4020_HW_CONF_OFF, value);
}

inline static void
mc_write_fifo_size (struct mc4020 *mc, int value)
{
  mc_write (mc, MC4020_FIFO_SIZE_OFF, value);
}

inline static void
mc_write_daq_atrig_lo (struct mc4020 *mc, int value)
{
  mc_write (mc, MC4020_DAQ_ATRIG_LO_OFF, value);
}

inline static void
mc_write_daq_atrig_hi (struct mc4020 *mc, int value)
{
  mc_write (mc, MC4020_DAQ_ATRIG_HI_OFF, value);
}

inline static void
mc_write_cr0 (struct mc4020 *mc, int value)
{
  mc_write (mc, MC4020_DAQ_CR0_OFF, value);
}

inline static void
mc_write_cr1 (struct mc4020 *mc, int value)
{
  mc_write (mc, MC4020_DAQ_CR1_OFF, value);
}

inline static void
mc_write_sample_interval (struct mc4020 *mc, unsigned long value)
{
  mc_write (mc, MC4020_DAQ_SAMPLE_INTERVAL_LO_OFF, value & 0xffff);
  mc_write (mc, MC4020_DAQ_SAMPLE_INTERVAL_HI_OFF, (value >> 16) & 0x00ff);
}

inline static void
mc_write_daq_count (struct mc4020 *mc, unsigned long value)
{
  mc_write (mc, MC4020_DAQ_COUNT_LO_OFF, value & 0xffff);
  mc_write (mc, MC4020_DAQ_COUNT_HI_OFF, (value >> 16) & 0x00ff);
}

inline static void
mc_write_soft_start (struct mc4020 *mc)
{
  mc_write (mc, MC4020_SOFT_START_OFF, 0);
}

inline static void
mc_write_single_conv_cmd (struct mc4020 *mc, int channel)
{
  mc_write (mc, MC4020_SINGLE_CONV_OFF, (channel & 0x3) << 8);
}

inline static void
mc_write_buffer_ptr_clear (struct mc4020 *mc)
{
  mc_write (mc, MC4020_BUFFER_PTR_CLEAR_OFF, 0);
}

inline static void
mc_write_DAC_cr1 (struct mc4020 *mc, int value)
{
  mc_write (mc, MC4020_DAC_CR1_OFF, value);
}

inline static void
mc_write_DAC0_data (struct mc4020 *mc, int value)
{
  mc_write (mc, MC4020_DAC0_DATA_LO_OFF, value & 0x00ff);
  mc_write (mc, MC4020_DAC0_DATA_HI_OFF, (value >> 8) & 0x000f);
}

inline static void
mc_write_DAC1_data (struct mc4020 *mc, int value)
{
  mc_write (mc, MC4020_DAC1_DATA_LO_OFF, value & 0x00ff);
  mc_write (mc, MC4020_DAC1_DATA_HI_OFF, (value >> 8) & 0x000f);
}

/* --- read only regs --- */

inline static u16
mc_read_hw_status (struct mc4020 *mc)
{
  u16 s = mc_read (mc, MC4020_HW_STATUS_OFF);
  mc->last_hw_status = s;
  return s;
}

inline static u16
mc_read_adc_read_ptr (struct mc4020 *mc)
{
  return mc_read (mc, MC4020_ADC_READ_PTR_REG_OFF);
}

inline static u16
mc_read_adc_write_ptr (struct mc4020 *mc)
{
  return mc_read (mc, MC4020_ADC_WRITE_PTR_REG_OFF);
}

inline static u16
mc_read_user_xfer_count (struct mc4020 *mc)
{
  return mc_read (mc, MC4020_USER_XFER_COUNT_OFF);
}

inline static u16
mc_read_pre_post_reg (struct mc4020 *mc)
{
  return mc_read (mc, MC4020_PRE_POST_REG_OFF);
}


// returns two samples packed in a 32-bit word

inline static u32
mc_read_fifo (struct mc4020 *mc)
{
  return readl (mc->fifo_vaddr + MC4020_BAR3_FIFO_OFF);
}


/* --- read/write regs --- */

inline static void
mc_write_82c55_port_a (struct mc4020 *mc, int value)
{
  mc_write (mc, MC4020_82C55_PORT_A, value & 0xff);
}

inline static void
mc_write_82c55_port_b (struct mc4020 *mc, int value)
{
  mc_write (mc, MC4020_82C55_PORT_B, value & 0xff);
}

inline static void
mc_write_82c55_port_c (struct mc4020 *mc, int value)
{
  mc_write (mc, MC4020_82C55_PORT_C, value & 0xff);
}

inline static void
mc_write_82c55_ctrl_port (struct mc4020 *mc, int value)
{
  mc_write (mc, MC4020_82C55_CTRL_PORT, value & 0xff);
}

inline static int
mc_read_82c55_port_a (struct mc4020 *mc)
{
  return mc_read (mc, MC4020_82C55_PORT_A);
}

inline static int
mc_read_82c55_port_b (struct mc4020 *mc)
{
  return mc_read (mc, MC4020_82C55_PORT_B);
}

inline static int
mc_read_82c55_port_c (struct mc4020 *mc)
{
  return mc_read (mc, MC4020_82C55_PORT_C);
}

inline static int
mc_read_82c55_ctrl_port (struct mc4020 *mc)
{
  return mc_read (mc, MC4020_82C55_CTRL_PORT);
}

/* --- plx register access --- */

inline static long
read_plx_intcsr (struct mc4020 *mc)
{
  return readl (mc->plx_vaddr + PLX_INTCSR);
}

inline static void
write_plx_intcsr (struct mc4020 *mc, long value)
{
  writel (value, mc->plx_vaddr + PLX_INTCSR);
}

inline static long
read_plx_cntrl (struct mc4020 *mc)
{
  return readl (mc->plx_vaddr + PLX_CNTRL);
}

inline static void
write_plx_cntrl (struct mc4020 *mc, long value)
{
  writel (value, mc->plx_vaddr + PLX_CNTRL);
}

inline static long
read_plx_dma1_mode (struct mc4020 *mc)
{
  return readl (mc->plx_vaddr + PLX_DMA1_MODE);
}

inline static void
write_plx_dma1_mode (struct mc4020 *mc, long value)
{
  writel (value, mc->plx_vaddr + PLX_DMA1_MODE);
}

inline static long
read_plx_dma1_pci_addr (struct mc4020 *mc)
{
  return readl (mc->plx_vaddr + PLX_DMA1_PCI_ADDR);
}

inline static void
write_plx_dma1_pci_addr (struct mc4020 *mc, long value)
{
  writel (value, mc->plx_vaddr + PLX_DMA1_PCI_ADDR);
}

inline static long
read_plx_dma1_lcl_addr (struct mc4020 *mc)
{
  return readl (mc->plx_vaddr + PLX_DMA1_LCL_ADDR);
}

inline static void
write_plx_dma1_lcl_addr (struct mc4020 *mc, long value)
{
  writel (value, mc->plx_vaddr + PLX_DMA1_LCL_ADDR);
}

inline static long
read_plx_dma1_size (struct mc4020 *mc)
{
  return readl (mc->plx_vaddr + PLX_DMA1_SIZE);
}

inline static void
write_plx_dma1_size (struct mc4020 *mc, long value)
{
  writel (value, mc->plx_vaddr + PLX_DMA1_SIZE);
}

inline static long
read_plx_dma1_descriptor (struct mc4020 *mc)
{
  return readl (mc->plx_vaddr + PLX_DMA1_DESCRIPTOR);
}

inline static void
write_plx_dma1_descriptor (struct mc4020 *mc, long value)
{
  writel (value, mc->plx_vaddr + PLX_DMA1_DESCRIPTOR);
}

inline static long
read_plx_dma1_csr (struct mc4020 *mc)
{
  return readb (mc->plx_vaddr + PLX_DMA1_CSR);
}

inline static void
write_plx_dma1_csr (struct mc4020 *mc, long value)
{
  writeb (value, mc->plx_vaddr + PLX_DMA1_CSR);
}

inline static long
read_plx_dma_threshold (struct mc4020 *mc)
{
  return readl (mc->plx_vaddr + PLX_DMA_THRESH);
}

inline static void
write_plx_dma_threshold (struct mc4020 *mc, long value)
{
  writel (value, mc->plx_vaddr + PLX_DMA_THRESH);
}

inline static long
read_plx_dma_arb (struct mc4020 *mc)
{
  return readl (mc->plx_vaddr + PLX_DMA_ARB);
}

inline static void
write_plx_dma_arb (struct mc4020 *mc, long value)
{
  writel (value, mc->plx_vaddr + PLX_DMA_ARB);
}


#endif /* _MC4020_UTIL_H_ */
