/**
 * @file avmdma.h
 *
 * AvmDma - Common definitions for AVM-B1 PCI v4 and AVM-T1 PCI.
 *
 * Copyright: 2000-2003 Thomas Wintergerst. All rights reserved.
 *
 * $FreeBSD$
 * $Id: avmdma.h,v 1.1.2.1 2006/02/28 21:35:09 thomas Exp $
 * Project  CAPI for BSD
 * Target   avmaic - CAPI manager driver for AVM active ISDN controllers
 * @date    01.01.2000
 * @author  "Thomas Wintergerst" <twinterg@gmx.de>
 * <p>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * </p>
 */

#ifndef __AVMDMA_H
#define __AVMDMA_H

#include <sys/types.h> /* size_t */
#include <machine/clock.h>
#include <machine/bus.h>

#include <c4b/avmaic/avmaic_var.h>
#include <c4b/avmaic/avmaic_misc.h>
#include <c4b/avmaic/avmio.h>
#include <c4b/avmaic/avmlli.h>





/* === public declarations =============================================== */





/* === prototypes of interface functions ================================= */





/* --- functions for direct communication with the board --- */

/* check for filled i/o receive buffer */
static __inline int avmdma_io_rx_full
   (bus_space_tag_t    t,
    bus_space_handle_t h);
    
/* check for empty i/o send buffer */
static __inline int avmdma_io_tx_empty
   (bus_space_tag_t    t,
    bus_space_handle_t h);

/**
 * Read byte of data from the controller with timeout.
 *
 * @param t                     I: Tag for i/o operations.
 * @param h                     I: Handle for i/o operations.
 * @param pucVal                O: The value read if result null.
 *
 * @retval 0                    Byte was successfully read.
 * @retval -1                   Failure.
 */
extern int avmdma_io_get_byte
   (bus_space_tag_t     iot,
    bus_space_handle_t  ioh,
    unsigned char      *pucVal);

/**
 * Write a byte of data to the controller with timeout.
 *
 * @param iot                   I: Tag for i/o operations.
 * @param ioh                   I: Handle for i/o operations.
 * @param ucVal                 I: The value to write.
 *
 * @retval 0                    The write operation was successful.
 * @retval -1                   The write operation failed because of a timeout.
 */
extern int avmdma_io_put_byte
   (bus_space_tag_t    iot,
    bus_space_handle_t ioh,
    unsigned char      ucVal);

/* get 32-bit word of data from controller */
static __inline int avmdma_io_get_word  /* 0: word successfully read
                                         * -1: failure
                                         */
   (bus_space_tag_t     iot,            /* I: bus tag for communication */
    bus_space_handle_t  ioh,            /* I: bus handle for communication */
    unsigned int       *puVal);         /* O: the value read if result 0 */

/* write 32-bit word of data to controller */
static __inline int avmdma_io_put_word  /* 0: word successfully written
                                         * -1: failure
                                         */
   (bus_space_tag_t    iot,             /* I: bus tag for communication */
    bus_space_handle_t ioh,             /* I: bus handle for communication */
    unsigned int       uVal);           /* I: the value to write */
    
/**
 * Read data from internal controller registers.
 *
 * @param iot                   I: But tag for communication.
 * @param ioh                   I: Bus handle for communication.
 * @param iReg                  I: The register to read from.
 * @param puVal                 O: The value read from the register if result 0.
 *
 * @retval 0                    The register was read successfully.
 * @retval -1                   Failure.
 */
extern int avmdma_io_read_reg
   (bus_space_tag_t     iot,
    bus_space_handle_t  ioh,
    int                 iReg,
    unsigned int       *puVal);

/**
 * Write data to internal controller registers.
 *
 * @param iot                   I: But tag for communication.
 * @param ioh                   I: Bus handle for communication.
 * @param iReg                  I: The register to write to.
 * @param uVal                  I: The value to write.
 *
 * @retval 0                    The register was successfully written to.
 * @retval -1                   Failure.
 */
extern int avmdma_io_write_reg
   (bus_space_tag_t    iot,
    bus_space_handle_t ioh,
    int                iReg,
    unsigned int       uVal);

/* switch test bit on or off */
static __inline int avmdma_io_set_test_bit
                                        /* 0: test bit set successfully
                                         * -1: failure
                                         */
   (bus_space_tag_t    iot,             /* I: bus tag for communication */
    bus_space_handle_t ioh,             /* I: bus handle for communication */
    int                fOn);            /* I: 0: switch test bit off
                                         * I: 1: switch test bit on
                                         */

/* read test bit */
static __inline int avmdma_io_get_test_bit
                                        /* 0: test bit is not set
                                         * 1: test bit is set
                                         * -1: failure
                                         */
   (bus_space_tag_t    iot,             /* I: bus tag for communication */
    bus_space_handle_t ioh);            /* I: bus handle for communication */

/* read one discrete 32-bit value from a memory i/o location */
static __inline u_int32_t avmdma_mem_readl
   (bus_space_tag_t    memt,
    bus_space_handle_t memh,
    u_int32_t          ulOffset);

/* write one discrete 32-bit value to a memory i/o location */
static __inline void avmdma_mem_writel
   (bus_space_tag_t    memt,
    bus_space_handle_t memh,
    u_int32_t          ulOffset,
    u_int32_t          ulValue);

/**
 * Detect a dma based board (B1 PCI v4 or T1 PCI).
 *
 * @param dev                   I: The device to check.
 * @param memt                  I: Bus tag for memory mapped communication.
 * @param memh                  I: Bus handle for memory mapped communication.
 * @param iot                   I: Bus tag for i/o port based communication.
 * @param ioh                   I: Bus handle for i/o port based communication.
 * @param cardType              I: The card type to check for (only B1 PCI v4 or
 *                                 T1 PCI allowed).
 *
 * @retval 0                    A board of the card type specified was detected.
 * @retval -1                   No DMA based board found or the board is not
 *                              working.
 */
extern int avmdma_detect
   (device_t           dev,
    bus_space_tag_t    memt,
    bus_space_handle_t memh,
    bus_space_tag_t    iot,
    bus_space_handle_t ioh,
    AvmAicCardType_t   cardType);

/* reset a dma based board */
extern void avmdma_reset
   (bus_space_tag_t    memt,
    bus_space_handle_t memh,
    bus_space_tag_t    iot,
    bus_space_handle_t ioh,
    AvmAicCardType_t   cardType);



/* --- performing board specific parts of CAPI calls --- */

/* register a CAPI application at a controller */
extern unsigned avmdma_app_register
   (AvmAicSc_t       *pSc,
    AvmAicPortData_t *pPortData,
    unsigned          uMaxLogicalConnections,
    unsigned          uMaxBDataBlocks,
    unsigned          uMaxBDataLen,
    unsigned          uApplID);

/* release a CAPI application at a controller */
extern unsigned avmdma_app_release
   (AvmAicSc_t       *pSc,
    AvmAicPortData_t *pPortData,
    unsigned          uApplID);

/* send a CAPI message to the controller */
extern unsigned avmdma_put_message
   (AvmAicSc_t       *pSc,
    AvmAicPortData_t *pPortData,
    unsigned          uApplID,
    struct mbuf      *pmbMsg);

/* reset and download a controller */
extern unsigned avmdma_reset_ctlr
                                        /* CAPI_OK or CAPI error value */
   (AvmAicSc_t *pSc,                    /* I: softc structure ident. the board
                                         */
    size_t               nNumDataBlocks,/* I: Number of data blocks to be sent
                                         *    to the controller; length of
                                         *    paDataBlocks
                                         */
    CAPICtlrDataBlock_t *paDataBlocks); /* I: Array of data blocks to be sent
                                         *    to the controller
                                         */



/* --- handling interrupt calls of the controllers --- */

/* the interrupt routine for a dma based board */
extern void avmdma_intr
   (AvmAicSc_t *pSc);

/* receive a CAPI message (but not a data-b3-indication) from a controller */
extern void avmdma_receive_message
   (AvmAicSc_t *pSc);
   
/* receive a data-b3-indication from an i/o based controller */
extern void avmdma_receive_data_b3_ind
   (AvmAicSc_t *pSc);
   
/* receive information about a new established B3 connection */
extern void avmdma_receive_new_ncci
   (AvmAicSc_t *pSc);
   
/* receive information about a released B3 connection or application */
extern void avmdma_receive_free_ncci
   (AvmAicSc_t *pSc);

/* receive acknowledge from initialization */
extern void avmdma_receive_init
   (AvmAicSc_t *pSc);

/* handle a message for a completed task */
extern void avmdma_receive_task_ready
   (AvmAicSc_t *pSc);

/* handle a debugging message */
extern void avmdma_receive_debugmsg
   (AvmAicSc_t *pSc);





/* === definition of inline functions ==================================== */





/*
	check for filled i/o receive buffer
	-----------------------------------
        
        Parameters:
           iot                  I: bus tag for communication
           ioh                  I: bus handle for communication

        Result:
           0                    receive buffer is not filled
           1                    receive buffer is filled
*/

static __inline int avmdma_io_rx_full
   (bus_space_tag_t    iot,
    bus_space_handle_t ioh)
{
   return ((bus_space_read_1 (iot, ioh, AVMAIC_REG_INSTAT) & 0x01) != 0);
} /* avmdma_io_rx_full */





/*
	check for empty i/o send buffer
	-------------------------------
        
        Parameters:
           iot                  I: bus tag for communication
           ioh                  I: bus handle for communication

        Result:
           0                    send buffer is not empty
           1                    send buffer is empty
*/

static __inline int avmdma_io_tx_empty
   (bus_space_tag_t    iot,
    bus_space_handle_t ioh)
{
   return ((bus_space_read_1 (iot, ioh, AVMAIC_REG_OUTSTAT) & 0x01) != 0);
} /* avmdma_io_tx_empty */





/*
        get 32-bit word of data from controller
        ---------------------------------------
        
        Parameters:
           iot                  I: bus tag for communication
           ioh                  I: bus handle for communication
           puVal                O: the value read if result 0
           
        Result:
           0                    word successfully read
           -1                   failure
*/

static __inline int avmdma_io_get_word
   (bus_space_tag_t     iot,
    bus_space_handle_t  ioh,
    unsigned int       *puVal)
{
   unsigned char uc1;
   unsigned char uc2;
   unsigned char uc3;
   unsigned char uc4;

   if (avmdma_io_get_byte (iot, ioh, &uc1) != 0 ||
       avmdma_io_get_byte (iot, ioh, &uc2) != 0 ||
       avmdma_io_get_byte (iot, ioh, &uc3) != 0 ||
       avmdma_io_get_byte (iot, ioh, &uc4) != 0)
   {
      return (-1);
   }
   *puVal = (unsigned int) uc1;
   *puVal |= (unsigned int) uc2 << 8;
   *puVal |= (unsigned int) uc3 << 16;
   *puVal |= (unsigned int) uc4 << 24;

   return (0);
} /* avmdma_io_get_word */





/*
        write 32-bit word of data to controller
        ---------------------------------------
        
        Parameters:
           iot                  I: bus tag for communication
           ioh                  I: bus handle for communication
           uVal                 I: the value to write
           
        Result:
           0                    word successfully written
           -1                   failure
*/

static __inline int avmdma_io_put_word
   (bus_space_tag_t    iot,
    bus_space_handle_t ioh,
    unsigned int       uVal)
{
   if (avmdma_io_put_byte (iot, ioh, uVal & 0xFF) != 0 ||
       avmdma_io_put_byte (iot, ioh, (uVal >> 8) & 0xFF) != 0 ||
       avmdma_io_put_byte (iot, ioh, (uVal >> 16) & 0xFF) != 0 ||
       avmdma_io_put_byte (iot, ioh, (uVal >> 24) & 0xFF) != 0)
   {
      return (-1);
   }
   return (0);
} /* avmdma_io_put_word */




    
/*
        switch test bit on or off
        -------------------------
        
        Parameters:
           iot                  I: bus tag for communication
           ioh                  I: bus handle for communication
           fOn                  I: 0: switch test bit off
                                   1: switch test bit on

        Result:
           0                    test bit set successfully
           -1                   failure
*/

static __inline int avmdma_io_set_test_bit
   (bus_space_tag_t    iot,
    bus_space_handle_t ioh,
    int                fOn)
{
   return (avmdma_io_write_reg (iot, ioh,
                                AVMAIC_INTREG_STAT0, fOn ? 0x21 : 0x20));
} /* avmdma_io_set_test_bit */





/*
        read test bit
        -------------
        
        Parameters:
           iot                  I: bus tag for communication
           ioh                  I: bus handle for communication

        Result:
           0                    test bit is not set
           1                    test bit is set
           -1                   failure
*/

static __inline int avmdma_io_get_test_bit
   (bus_space_tag_t    iot,
    bus_space_handle_t ioh)
{
   unsigned int uVal;
   
   if (avmdma_io_read_reg (iot, ioh, AVMAIC_INTREG_STAT0, &uVal) != 0)
   {
      return (-1);
   }
   return ((uVal & 0x01) != 0);
} /* avmdma_io_get_test_bit */





/*
        read one discrete 32-bit value from a memory i/o location
        ---------------------------------------------------------
*/

static __inline u_int32_t avmdma_mem_readl
   (bus_space_tag_t    memt,
    bus_space_handle_t memh,
    u_int32_t          ulOffset)
{
   return (le32toh (bus_space_read_4 (memt, memh, ulOffset)));
} /* avmdma_mem_readl */





/*
        write one discrete 32-bit value to a memory i/o location
        --------------------------------------------------------
*/

static __inline void avmdma_mem_writel
   (bus_space_tag_t    memt,
    bus_space_handle_t memh,
    u_int32_t          ulOffset,
    u_int32_t          ulValue)
{
   bus_space_write_4 (memt, memh, ulOffset, htole32 (ulValue));
} /* avmdma_mem_writel */





#endif /* __AVMDMA_H */
