/******************************************************************************
 *
 * proatm.h
 *
 * Date: 02/09/2026
 *
 * Header file for the LINUX proatm driver for PROATM cards.
 *
 * Author: Christian Bucari: bucari@prosum.net
 * Copyright (c) 2002-2018 Prosum
 *
 ******************************************************************************
 *
 * This program 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. 
 * You should have received a copy of the  GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 ******************************************************************************
 */

#ifndef _LINUX_PROATM_H
#define _LINUX_PROATM_H

#if LINUX_VERSION_CODE < KERNEL_VERSION (2,6,0)
#error This driver cannot be used with linux versions older than 2.6.0. Use nicstar2 instead.
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0)
	#include <linux/dma-mapping.h>
	static inline void *

	/* This defines the direction arg to the DMA mapping routines. */
	#define PCI_DMA_BIDIRECTIONAL	DMA_BIDIRECTIONAL
	#define PCI_DMA_TODEVICE		DMA_TO_DEVICE
	#define PCI_DMA_FROMDEVICE		DMA_FROM_DEVICE
	#define PCI_DMA_NONE			DMA_NONE

	pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
						dma_addr_t *dma_handle)
	{
		   return dma_alloc_coherent(&hwdev->dev, size, dma_handle, GFP_ATOMIC);
	}

	static inline void
	pci_free_consistent(struct pci_dev *hwdev, size_t size,
					   void *vaddr, dma_addr_t dma_handle)
	{
		   dma_free_coherent(&hwdev->dev, size, vaddr, dma_handle);
	}
	static inline dma_addr_t
	pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, int direction)
	{
		  return dma_map_single(&hwdev->dev, ptr, size, (enum dma_data_direction)direction);
	}

	static inline void
	pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
					size_t size, int direction)
	{
		   dma_unmap_single(&hwdev->dev, dma_addr, size, (enum dma_data_direction)direction);
	}
	static inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask)
	{
		   return dma_set_mask(&dev->dev, mask);
	}
	static inline void
	pci_dma_sync_single_for_cpu(struct pci_dev *hwdev, dma_addr_t dma_handle,
			    size_t size, int direction)
	{
		dma_sync_single_for_cpu(&hwdev->dev, dma_handle, size, (enum dma_data_direction)direction);
	}

	static inline void
	pci_dma_sync_single_for_device(struct pci_dev *hwdev, dma_addr_t dma_handle,
			    size_t size, int direction)
	{
		dma_sync_single_for_device(&hwdev->dev, dma_handle, size, (enum dma_data_direction)direction);
	}

#endif


#define PROATM_VERSION "3.71"

/* Options ********************************************************************/

/* 
 * Enable RAW CELL QUEUE receipt 
 */
#define PROATM_RCQ_SUPPORT

/*
 * AAL0 cells are placed into the raw cell queue.
 * 
 * When this option is set (default), all incoming AAL0 cells produce a receive
 * interrupt regardless of the PTI bit value.
 * When this option is NOT set, AAL0 cells go to standard queues and the SAR 
 * reassembles AAL0 cells into AAL0 PDUs. The last cell is supposed to have 
 * PTI bit0 = 1, which generates the receive interrupt. Cells with PTI bit0 = 0 
 * do not produce any interrupt.
 * Please note that current Linux ATM implementation does not permit AAL0
 * PDUs larger than one cell.
 */
#define PROATM_AAL0_TO_RCQ


/* 
 * The header of AAL0 cells is build from connection information                                    
 *
 * When this option is NOT set (default), according to the Linux ATM API the
 * header is simply taken from the first 4 bytes of each SKB data. 
 * Note that incorrect headers may hang the driver and the computer.
 * When this option is set, the header of AAL0 cells is built by the driver 
 * similarly to AAL5 cells. The first 4 bytes of packets are ignored except
 * the GFC and PTI.
 */
#undef PROATM_BUILD_AAL0_HEADER

          
/*
 * Print a message on each raw cell receipt.
 * 
 * Most of time, raw cells are cells received on non open VCs. Disable this
 * option if you receive too many raw cells under normal conditions 
 */          
#undef PROATM_PRINT_RAW_CELL_MESSAGE


/* 
 * Define the number of bits used to code the VPI: 0, 1, 2, or 8 
 */
#define PROATM_VPIBITS 2


/*
 * Define the smaller VPI and the smaller VCI. This permits to 
 * change the range of supported VPI and VCI to fit specific applications. 
 * PROATM_VPIBASE is smaller than 256. PROATM_VCIBASE is smaller than 64536. 
 * Refer to the README for more detail information. 
 */            
#define PROATM_VCIBASE 0
#define PROATM_VPIBASE 0


/* 
 * 4032, 8064 or 16128
 */        
#define PROATM_B1BUFSIZE 8064


/* 
 * Number of entries reserved for UBR/ABR/VBR 
 */      
#define PROATM_TST_RESERVED 340     


/* 
 * By default, the physical interface of PROATM-155 cards implements OC3 
 * and partial SDH. This works in most cases. 
 * Set this option to make the physical interface implement full SDH. (no more 
 * OC3 compatible)
 */                            
#undef  PROATM_SUNI_FULL_SDH

/*
 * OAM Support  
 */
#undef PROATM_OAM_SUPPORT

/* Location ID for Fault Management*/
#define PROATM_LLID {0x6A,0x6A,0x6A,0x6A,0x6A,0x6A,0x6A,0x6A,  \
                 0x6A,0x6A,0x6A,0x6A,0x6A,0x6A,0x6A,0x6A}


/*
 * Use a workqueue to transmit SKBs to upper ATM network layers outside the
 * interrupt context.
 * This option makes the ping response time much longer but improves the
 * average throughput of small packets. It typically provides twice better
 * throughput for raw cell queue AAL0 - see NS_RCQ_SUPPORT option above.
 * It may also fix some hardlock problems on some architectures.
 */
#define PROATM_USE_WORKQUEUE

        
/******************************************************************************/

/* Threshold values : reg #38-#41*/
/* unit = 512/16 = 32 */
#define PROATM_B0THLD    0x0
#define PROATM_B1THLD    (0x1<<28)
#define PROATM_B2THLD    0x0
#define PROATM_B3THLD    0x0
#define PROATM_B0NITHLD  0x0
#define PROATM_B1NITHLD  0x0
#define PROATM_B2NITHLD  0x0
#define PROATM_B3NITHLD  0x0
#define PROATM_B0CITHLD  0x0
#define PROATM_B1CITHLD  0x0
#define PROATM_B2CITHLD  0x0
#define PROATM_B3CITHLD  0x0
#define PROATM_B0SIZE    (PROATM_B0BUFSIZE/48)  /*5*/
#define PROATM_B1SIZE    (PROATM_B1BUFSIZE/48)  

/* Number of free rx buffers initially allocated */
#define NUM_B0 0
#define NUM_B1 64

/* Free buffers queue pointers */
#define PROATM_FBQ0_RP  0x0 
#define PROATM_FBQ0_WP  0x00000000 /*NUM_B0=32 in decimal */
#define PROATM_FBQ1_RP  0x0 
#define PROATM_FBQ1_WP  0x00000000 /*NUM_B1=32 in decimal */
#define PROATM_FBQ2_RP  0x0 
#define PROATM_FBQ2_WP  0x0
#define PROATM_FBQ3_RP  0x0 
#define PROATM_FBQ3_WP  0x0

/* Lower level for count of free rx buffers */
#define MIN_B0 0
#define MIN_B1 16

/* Upper level for count of free rx buffers */
#define MAX_B0 512
#define MAX_B1 512


#define MAX_TBD_PER_VC 1        /* Number of TBDs before a TSR */
#define MAX_TBD_PER_SCQ 20      /* Only meaningful for variable rate SCQs */

#define SCQFULL_TIMEOUT (5 * HZ)

#define PROATM_POLL_PERIOD (HZ)

#define PCR_TOLERANCE (1.0001)


/* ESI stuff ******************************************************************/

#define PROATM_EPROM_PROSUM_MAC_ADDR_OFFSET 36
#define PROATM_EPROM_IDT_MAC_ADDR_OFFSET 0x6C 
#define PROSUM_MAC_0 0x00
#define PROSUM_MAC_1 0xC0
#define PROSUM_MAC_2 0xFD

/* #defines *******************************************************************/

#define PROATM_MAX_CARDS 5          /* Maximum number of cards. Must be <= 5 */
#define PROATM_RSQSIZE 8192         /* 2048, 4096 or 8192 */
#define PROATM_IOREMAP_SIZE 4096

#define BUF_B0 1       /* These are used for push_rxbufs() */
#define BUF_B1 2       /* register CMD, Write_FreeBufQ : BUFQS bits */
#define BUF_HB 3

#define PROATM_HBUFSIZE 65568       /* Size of max. AAL5 PDU */
#define PROATM_MAX_SKBUFFS (2 + (65568 - PROATM_B0BUFSIZE) / \
                       (PROATM_B1BUFSIZE - (PROATM_B1BUFSIZE % 48)))

#define PROATM_B0BUFSIZE 240    /*  48, 96, 240 or 2016 */
#define PROATM_B0SKBSIZE PROATM_B0BUFSIZE
#define PROATM_B1SKBSIZE PROATM_B1BUFSIZE

#define PROATM_AAL0_HEADER (ATM_AAL0_SDU - ATM_CELL_PAYLOAD)        /* 4 bytes */
 
/* OAM Function and type definitions */
#define OAM_ACT_DEACT_CC        0x81
#define OAM_LOOPBACK            0x18
#define OAM_AIS                 0x10
#define OAM_RDI                 0x11
#define OAM_CC                  0x14

/* OAM masks & values for various fields */
#define OAM_MASK_MSGID          0xFC
#define OAM_MASK_DIR            0x03
#define OAM_LOOPBACK_REPLY_MASK 0x01
#define OAM_ACTIVATE_REQUEST            0x04
#define OAM_ACTIVATE_CONFIRMED          0x08
#define OAM_ACTIVATE_REQUEST_DENIED     0x0C
#define OAM_DEACTIVATE_REQUEST          0x14
#define OAM_DEACTIVATE_CONFIRMED        0x18
#define OAM_DEACTIVATE_REQUEST_DENIED   0x1C

/* OAM cell types */
#define OAM_F4_SEG              0x01
#define OAM_F4_E2E              0x02
#define OAM_F5_SEG              0x03
#define OAM_F5_E2E              0x04


/* PROATM structures located in host memory **********************************/

/* RSQ - Receive Status Queue 
 *
 * Written by the SAR, read by the device driver.
 */

typedef struct proatm_rsqe
{
   u32 word_1;
   u32 buffer_handle;
   u32 final_aal5_crc32;
   u32 word_4;
} proatm_rsqe;

#define proatm_rsqe_vpi(proatm_rsqep) \
        ((le32_to_cpu((proatm_rsqep)->word_1) & 0x00FF0000) >> 16)
#define proatm_rsqe_vci(proatm_rsqep) \
        (le32_to_cpu((proatm_rsqep)->word_1) & 0x0000FFFF)

#define PROATM_RSQE_TYPE       0xC0000000 
#define PROATM_RSQE_VALID      0x80000000   /* still exists */
#define PROATM_RSQE_POOL       0x00030000
#define PROATM_RSQE_BUFASSIGN  0x00008000  
#define PROATM_RSQE_NZGFC      0x00004000
#define PROATM_RSQE_EOPDU      0x00002000
#define PROATM_RSQE_CBUF       0x00001000 
#define PROATM_RSQE_CONGESTION 0x00000800
#define PROATM_RSQE_CLP        0x00000400
#define PROATM_RSQE_CRCERR     0x00000200

#define PROATM_RSQE_BUFSIZE_B0 0x00000000
#define PROATM_RSQE_BUFSIZE_B1 0x00001000

#define proatm_rsqe_type(proatm_rsqep) \
        (le32_to_cpu((proatm_rsqep)->word_4) & PROATM_RSQE_TYPE)
#define proatm_rsqe_valid(proatm_rsqep) \
        (le32_to_cpu((proatm_rsqep)->word_4) & PROATM_RSQE_VALID)
#define proatm_rsqe_pool(proatm_rsqep) \
        (le32_to_cpu((proatm_rsqep)->word_4) & PROATM_RSQE_POOL)
#define proatm_rsqe_bufassign(proatm_rsqep) \
        (le32_to_cpu((proatm_rsqep)->word_4) & PROATM_RSQE_BUFASSIGN)
#define proatm_rsqe_nzgfc(proatm_rsqep) \
        (le32_to_cpu((proatm_rsqep)->word_4) & PROATM_RSQE_NZGFC)
#define proatm_rsqe_eopdu(proatm_rsqep) \
        (le32_to_cpu((proatm_rsqep)->word_4) & PROATM_RSQE_EOPDU)
#define proatm_rsqe_cbuf(proatm_rsqep) \
        (le32_to_cpu((proatm_rsqep)->word_4) & PROATM_RSQE_CBUF)
#define proatm_rsqe_congestion(proatm_rsqep) \
        (le32_to_cpu((proatm_rsqep)->word_4) & PROATM_RSQE_CONGESTION)
#define proatm_rsqe_clp(proatm_rsqep) \
        (le32_to_cpu((proatm_rsqep)->word_4) & PROATM_RSQE_CLP)
#define proatm_rsqe_crcerr(proatm_rsqep) \
        (le32_to_cpu((proatm_rsqep)->word_4) & PROATM_RSQE_CRCERR)

#define proatm_rsqe_cellcount(proatm_rsqep) \
        (le32_to_cpu((proatm_rsqep)->word_4) & 0x000001FF)
#define proatm_rsqe_init(proatm_rsqep) \
        ((proatm_rsqep)->word_4 = cpu_to_le32(0x00000000)) 

#define PROATM_RSQ_NUM_ENTRIES (PROATM_RSQSIZE / 16)
#define PROATM_RSQ_ALIGNMENT PROATM_RSQSIZE



/* RCQ - Raw Cell Queue
 *
 * Written by the SAR, read by the driver.
 */

typedef struct proatm_rcqe
{
   u32 word_1;
   u32 word_2;
   u32 word_3;
   u32 word_4;
   u8 payload[ATM_CELL_PAYLOAD];
} proatm_rcqe;

#define PROATM_RCQE_SIZE 64         /* bytes */

#define rcqe_islast(proatm_rcqep) \
        (le32_to_cpu((proatm_rcqep)->word_2) != 0x00000000)
#define rcqe_cellheader(proatm_rcqep) \
        (le32_to_cpu((proatm_rcqep)->word_1))
#define rcqe_nextbufhandle(proatm_rcqep) \
        (le32_to_cpu((proatm_rcqep)->word_2))




/* SCQ - Segmentation Channel Queue 
 *
 * Written by the device driver, read by the SAR.
 */

typedef struct proatm_scqe
{
   u32 word_1;
   u32 word_2;
   u32 word_3;
   u32 word_4;
} proatm_scqe;

   /* NOTE: SCQ entries can be either a TBD (Transmit Buffer Descriptors)
            or TSR (Transmit Status Requests) */

#define PROATM_SCQE_TYPE_TBD 0x00000000
#define PROATM_SCQE_TYPE_TSR 0x80000000

/* used for flags in proatm_tbd_mkword_1 and proatm_tbd_mkword_1_novbr*/
#define PROATM_TBD_EOPDU 0x40000000
#define PROATM_TBD_AAL0  0x00000000
#define PROATM_TBD_AAL34 0x04000000
#define PROATM_TBD_AAL5  0x08000000
#define PROATM_TBD_OAM   0x10000000
#define PROATM_TBD_TSIF  0x20000000
#define PROATM_TBD_GTSI  0x02000000

#define PROATM_TBD_VPI_MASK 0x0FF00000
#define PROATM_TBD_VCI_MASK 0x000FFFF0
#define PROATM_TBD_VC_MASK (PROATM_TBD_VPI_MASK | PROATM_TBD_VCI_MASK)

#define PROATM_TBD_VPI_SHIFT 20
#define PROATM_TBD_VCI_SHIFT 4

#define proatm_tbd_mkword_1(flags, tsrtag, buflen) \
      (cpu_to_le32((flags) | tsrtag <<20 | (buflen)))

#define proatm_tbd_mkword_3(control, pdulen) \
      (cpu_to_le32((control) << 16 | (pdulen)))

#define proatm_tbd_mkword_4(gfc, vpi, vci, pt, clp) \
      (cpu_to_le32((gfc) << 28 | (vpi) << 20 | (vci) << 4 | (pt) << 1 | (clp)))



#define PROATM_TSR_TSIF        0x20000000

#define PROATM_TSR_SCDISUBR0 0xFFFF         /* Use as scdi for SCD reserved for UBR */
                                                            /* unspecified pcr */

#define proatm_tsr_mkword_1(flags) \
        (cpu_to_le32(PROATM_SCQE_TYPE_TSR | (flags)))

#define proatm_tsr_mkword_2(scdi, scqi) \
        (cpu_to_le32((scdi) << 16 | 0x00008000 | (scqi)))

#define proatm_scqe_is_tsr(proatm_scqep) \
        (le32_to_cpu((proatm_scqep)->word_1) & PROATM_SCQE_TYPE_TSR)


#define SCQ_NUM_ENTRIES 64  /* 1024/16 */
#define SCQ_SIZE 1024 
#define PROATM_SCQE_SIZE 16




/* TSQ - Transmit Status Queue
 *
 * Written by the PROATM, read by the device driver.
 */

typedef struct proatm_tsi
{
   u32 word_1;
   u32 word_2;
} proatm_tsi;

   /* NOTE: The first word can be a status word copied from the TSR which
            originated the TSI, or a timer overflow indicator. In this last
                case, the value of the first word is all zeroes. */

#define PROATM_TSI_EMPTY          0x80000000
#define PROATM_TSI_TIMESTAMP_MASK 0x00FFFFFF
#define PROATM_TSI_TYPE_MASK      0x60000000
#define PROATM_TSI_TYPE_TMROF     0x00000000
#define PROATM_TSI_TYPE_TSR       0x20000000
#define PROATM_TSI_TYPE_IDLE      0x40000000
#define PROATM_TSI_TYPE_TBD       0x60000000

#define proatm_tsi_isempty(proatm_tsip) \
        (le32_to_cpu((proatm_tsip)->word_2) & PROATM_TSI_EMPTY)
#define proatm_tsi_gettimestamp(proatm_tsip) \
        (le32_to_cpu((proatm_tsip)->word_2) & PROATM_TSI_TIMESTAMP_MASK)
#define proatm_tsi_gettype(proatm_tsip) \
        (le32_to_cpu((proatm_tsip)->word_2) & PROATM_TSI_TYPE_MASK) 
#define proatm_tsi_init(proatm_tsip) \
        ((proatm_tsip)->word_2 = cpu_to_le32(PROATM_TSI_EMPTY))
    
        
#define PROATM_TSQSIZE 8192
#define PROATM_TSQ_NUM_ENTRIES 1024
#define PROATM_TSQ_ALIGNMENT 8192


#define PROATM_TSI_SCDISUBR0 PROATM_TSR_SCDISUBR0  /* i.e. 0xFFFF */

#define proatm_tsi_getword_1(proatm_tsip) \
        (le32_to_cpu((proatm_tsip)->word_1))
#define proatm_tsi_getword_2(proatm_tsip) \
        (le32_to_cpu((proatm_tsip)->word_2))        

/* timer overflow */
#define proatm_tsi_tmrof(proatm_tsip) \
        (le32_to_cpu((proatm_tsip)->word_1) == 0x00000000)

/* if the TSI is due to a TBD, get VCI and VPI and tag */
#define proatm_tsi_getvci(proatm_tsip) \
        ((le32_to_cpu((proatm_tsip)->word_1) & 0x000FFFF0) >> 4)

#define proatm_tsi_getvpi(proatm_tsip) \
        ((le32_to_cpu((proatm_tsip)->word_1) & 0x0FF00000) >> 20)

#define proatm_tsi_gettag(proatm_tsip) \
        ((le32_to_cpu((proatm_tsip)->word_2) & 0x1F000000) >> 24)
         
/* if the TSI is due to a TSR, status word of the TSR is copied in 1st TSI word
 */
#define proatm_tsi_getscdindex(proatm_tsip) \
        ((le32_to_cpu((proatm_tsip)->word_1) & 0xFFFF0000) >> 16)
        
#define proatm_tsi_getscqpos(proatm_tsip) \
        (le32_to_cpu((proatm_tsip)->word_1) & 0x00007FFF)



/* PROATM structures located in local SRAM ***********************************/

/* TCT - Transmit Connection Table
 *
 * Written by both the SAR and the device driver.
 */
#define PROATM_TCT_ENTRY_SIZE      8

/* word 1 of TCTE */   
#define PROATM_TCTE_TYPE_MASK      0xC0000000
#define PROATM_TCTE_TYPE_CBR       0x00000000
#define PROATM_TCTE_TYPE_ABR       0x80000000
#define PROATM_TCTE_TYPE_VBR       0x40000000
#define PROATM_TCTE_TYPE_UBR       0x00000000
/* word 3 */
#define PROATM_TCTE_TSIF               (1<<14)
/* word 4 of TCTE */
#define PROATM_TCTE_HALT           0x80000000  
#define PROATM_TCTE_IDLE           0x40000000
/* word 8 of UBR or CBR TCTE */
#define PROATM_TCTE_UBR_EN         0x80000000  

    
/* RCT - Receive Connection Table
 *
 * Written by both the SAR and the device driver.
 */

typedef struct proatm_rcte
{
   u32 word_1;
   u32 buffer_handle;
   u32 dma_address;
   u32 aal5_crc32;
} proatm_rcte;


#define PROATM_RCTE_INACTLIM        0xE0000000
#define PROATM_RCTE_INACTCOUNT      0x1C000000
#define PROATM_RCTE_CIVC            0x00800000
#define PROATM_RCTE_FBP             0x00600000
#define PROATM_RCTE_FBP1                        0x00200000
/*#define PROATM_RCTE_BSFB            0x00200000 */ /* Rev. D only */
#define PROATM_RCTE_NZGFC           0x00100000
#define PROATM_RCTE_CONNECTOPEN     0x00080000
#define PROATM_RCTE_AALMASK         0x00070000
#define PROATM_RCTE_AAL0            0x00000000
#define PROATM_RCTE_AAL34           0x00010000
#define PROATM_RCTE_AAL5            0x00020000
#define PROATM_RCTE_RCQ             0x00030000
#define PROATM_RCTE_OAM             0x00040000
#define PROATM_RCTE_RAWCELLINTEN    0x00008000
#define PROATM_RCTE_RXCONSTCELLADDR 0x00004000
#define PROATM_RCTE_BUFSTAT         0x00003000
#define PROATM_RCTE_EFCI            0x00000800
#define PROATM_RCTE_CLP             0x00000400
#define PROATM_RCTE_CRCERROR        0x00000200
#define PROATM_RCTE_CELLCOUNT_MASK  0x000001FF

#define PROATM_RCT_ENTRY_SIZE 4     /* Number of dwords */

   /* NOTE: We could make macros to contruct the first word of the RCTE,
            but that doesn't seem to make much sense... */



/* FBD - Free Buffer Descriptor
 *
 * Written by the device driver using via the command register.
 */

typedef struct proatm_fbd
{
   u32 buffer_handle;
   u32 dma_address;
} proatm_fbd;


/* TST - Transmit Schedule Table
 *
 * Written by the device driver.
 */

typedef u32 proatm_tste;

#define PROATM_TST_OPCODE_MASK 0x60000000

#define PROATM_TST_OPCODE_NULL     0x00000000 /* Insert null cell */
#define PROATM_TST_OPCODE_FIXED    0x20000000 /* Cell from a fixed rate channel */
#define PROATM_TST_OPCODE_VARIABLE 0x40000000 /* Cell from variable rate channel */
#define PROATM_TST_OPCODE_END      0x60000000 /* Jump */

#define proatm_tste_make(opcode, sramad) (opcode | sramad)

   /* NOTE:

      - When the opcode is FIXED, sramad specifies the connection number used to
      index the TCT.
      - When the opcode is END, sramad specifies the SRAM address in bytes of the
        location of the next TST entry to read.
    */



/* SCD - Segmentation Channel Descriptor
 *
 * Written by both the device driver and the S
 */

typedef struct proatm_scd
{
   u32          word_1;
   u32          word_2;
   u32          partial_aal5_crc;
   u32          reserved;
   proatm_scqe      cache_a;
   proatm_scqe      cache_b;
} proatm_scd;

#define PROATM_SCD_ENTRY_SIZE 12

/* ABR SAR local SRAM memory map
 **********************************************/


/* TCT */
/* size set by CFG reg(b16-17)  8-words entries */

/* RCT */
/* size set by CFG reg(b16-17)  4-words entries */

/* RFBQ */  
#define PROATM_RFBQ_SIZE     0x400
 
/* DTST size set by ABRSTD (2x2Kword-tables) (and b0-11 null) */
#define PROATM_ABRVBRSIZE   (0x2<<24)
#define PROATM_DTST_SIZE 4096
  
/* TST */
#define PROATM_TST_SIZE_MAX         4096
#define PROATM_TST_RESERVED         340             /* entries reserved for UBR/ABR/VBR */

/* SCDs */
/* 12-word entries */
#define PROATM_SCD_NUM               250  /* max number of SCDs */

/* RXFIFO size set by RXFD (4K words) (and b0-13 null) */
#define PROATM_RXFIFO_SIZE          0x1000
#define PROATM_RXFD_SIZE            (3<<24)


/* NISCtAR operation registers ************************************************/


enum proatm_regs
{
   DR0   = 0x00,      /* Data Register 0 R/W*/
   DR1   = 0x04,      /* Data Register 1 W */
   DR2   = 0x08,      /* Data Register 2 W */
   DR3   = 0x0C,      /* Data Register 3 W */
   CMD   = 0x10,      /* Command W */
   CFG   = 0x14,      /* Configuration R/W */
   STAT  = 0x18,      /* Status R/W */
   RSQB  = 0x1C,      /* Receive Status Queue Base W */
   RSQT  = 0x20,      /* Receive Status Queue Tail R */
   RSQH  = 0x24,      /* Receive Status Queue Head W */
   CDC   = 0x28,      /* Cell Drop Counter R/clear */
   VPEC  = 0x2C,      /* VPI/VCI Lookup Error Count R/clear */
   ICC   = 0x30,      /* Invalid Cell Count R/clear */
   RAWCT = 0x34,      /* Raw Cell Tail R */
   TMR   = 0x38,      /* Timer R */
   TSTB  = 0x3C,      /* Transmit Schedule Table Base R/W */
   TSQB  = 0x40,      /* Transmit Status Queue Base W */
   TSQT  = 0x44,      /* Transmit Status Queue Tail R */
   TSQH  = 0x48,      /* Transmit Status Queue Head W */
   GP    = 0x4C,      /* General Purpose R/W */
   VPM   = 0x50,      /* VPI/VCI Mask W */
   RXFD  = 0x54,      /* Receive FIFO descriptor */ 
   RXFT  = 0x58,      /* Receive FIFO Tail */ 
   RXFH  = 0x5C,      /* Receive FIFO  Head */
   RAWHND= 0x60,      /* Raw Cell Handle register */ 
   RXSTAT= 0x64,      /* Receive Conn. State register */ 
   ABRSTD= 0x68,      /* ABR Schedule TableDescriptor */
   ABRRQ = 0x6C,      /* ABR Ready Queue Pointer register */
   VBRRQ = 0x70,      /* VBR Ready Queue Pointer register */
   RTBL  = 0x74,      /* Rate Table Descriptor */
   MXDFCT= 0x78,      /* Maximum Deficit Count register */
   TXSTAT= 0x7C,      /* Transmit Conn. State register */
   TCMDQ = 0x80,      /* Transmit Command Queue register */
   IRCP  = 0x84,      /* Inactive Receive Conn. Pointer */
   FBQP0 = 0x88,      /* Free Buffer Queue Pointer Register 0 */
   FBQP1 = 0x8C,      /* Free Buffer Queue Pointer Register 1 */
   FBQP2 = 0x90,      /* Free Buffer Queue Pointer Register 2 */
   FBQP3 = 0x94,      /* Free Buffer Queue Pointer Register 3 */
   FBQS0 = 0x98,      /* Free Buffer Queue Size Register 0 */
   FBQS1 = 0x9C,      /* Free Buffer Queue Size Register 1 */
   FBQS2 = 0xA0,      /* Free Buffer Queue Size Register 2 */
   FBQS3 = 0xA4,      /* Free Buffer Queue Size Register 3 */
   FBQWP0= 0xA8,      /* Free Buffer Queue Write Pointer Register 0 */
   FBQWP1= 0xAC,      /* Free Buffer Queue Write Pointer Register 1 */
   FBQWP2= 0xB0,      /* Free Buffer Queue Write Pointer Register 2 */
   FBQWP3= 0xB4,      /* Free Buffer Queue Write Pointer Register 3 */
   NOW   = 0xB8       /* Current Transmit Schedule Table Address */
};


/* SAR commands issued to the CMD register ********************************/


/* Top 4 bits are command opcode, lower 28 are parameters. */

#define PROATM_CMD_NO_OPERATION         0x00000000
        /* params always 0 */

#define PROATM_CMD_OPENCLOSE_CONNECTION 0x20000000
        /* b19{1=open,0=close} b18-2{SRAM addr} */

#define PROATM_CMD_WRITE_SRAM           0x40000000
        /* b18-2{SRAM addr} b1-0{burst size} */

#define PROATM_CMD_READ_SRAM            0x50000000
        /* b18-2{SRAM addr} */

#define PROATM_CMD_WRITE_FREEBUFQ       0x60000000
        /* b0{large buf indicator} */

#define PROATM_CMD_READ_UTILITY         0x80000000
        /* b8{1=select UTL_CS0} b9{1=select UTL_CS1} b7-0{bus addr} */

#define PROATM_CMD_WRITE_UTILITY        0x90000000
        /* b8{1=select UTL_CS0} b9{1=select UTL_CS1} b7-0{bus addr} */

#define PROATM_CMD_OPEN_CONNECTION (PROATM_CMD_OPENCLOSE_CONNECTION | 0x00080000)
#define PROATM_CMD_CLOSE_CONNECTION PROATM_CMD_OPENCLOSE_CONNECTION


/* SAR configuration bits *************************************************/

#define PROATM_CFG_SWRST          0x80000000    /* Software Reset */
#define PROATM_CFG_LOOP           0x40000000    /* Enable internal loop back */
#define PROATM_CFG_RXPATH         0x20000000    /* Receive Path Enable */
#define PROATM_CFG_IDLECLP        0x10000000    /* CLP bit of Null Cells */
#define PROATM_CFG_TFIFOSIZE_MASK 0x0C000000    /* Specifies size of tx FIFO */
#define PROATM_CFG_RSQSIZE_MASK   0x00C00000    /* Receive Status Queue Size */
#define PROATM_CFG_ICACCEPT       0x00200000    /* Invalid Cell Accept */
#define PROATM_CFG_IGNOREGFC      0x00100000    /* Ignore General Flow Control */
#define PROATM_CFG_VPIBITS_MASK   0x000C0000    /* VPI/VCI Bits Size Select */
#define PROATM_CFG_RCTSIZE_MASK   0x00030000    /* Receive Connection Table Size */
#define PROATM_CFG_VCERRACCEPT    0x00008000    /* VPI/VCI Error Cell Accept */
#define PROATM_CFG_RXINT_MASK     0x00007000    /* End of Receive PDU Interrupt
                                               Handling */
#define PROATM_CFG_RAWIE          0x00000800    /* Raw Cell Qu' Interrupt Enable */
#define PROATM_CFG_RSQAFIE        0x00000400    /* Receive Queue Almost Full
                                               Interrupt Enable */
#define PROATM_CFG_RXRM           0x00000200    /* Receive RM Cells */
#define PROATM_CFG_CACHE          0x00000100    /* Cache */
#define PROATM_CFG_TMRROIE        0x00000080    /* Timer Roll Over Interrupt
                                               Enable */
#define PROATM_CFG_FBIE           0x00000040    /* Free Buffer Queue Int Enable */          
                               

#define PROATM_CFG_TXEN           0x00000020    /* Transmit Operation Enable */
#define PROATM_CFG_TXIE           0x00000010    /* Transmit Status Interrupt
                                               Enable */
#define PROATM_CFG_TXURIE         0x00000008    /* Transmit Under-run Interrupt
                                               Enable */
#define PROATM_CFG_UMODE          0x00000004    /* Utopia Mode (cell/byte) Select */
#define PROATM_CFG_TSQFIE         0x00000002    /* Transmit Status Queue Full
                                               Interrupt Enable */
#define PROATM_CFG_PHYIE          0x00000001    /* PHY Interrupt Enable */

#define PROATM_CFG_RSQSIZE_2048 0x00000000
#define PROATM_CFG_RSQSIZE_4096 0x00400000
#define PROATM_CFG_RSQSIZE_8192 0x00800000

#define PROATM_CFG_VPIBITS_0 0x00000000
#define PROATM_CFG_VPIBITS_1 0x00040000
#define PROATM_CFG_VPIBITS_2 0x00080000
#define PROATM_CFG_VPIBITS_8 0x000C0000

#define PROATM_CFG_RCTSIZE_1024_ENTRIES  0x00000000   /* the one used */
#define PROATM_CFG_RCTSIZE_4096_ENTRIES  0x00010000
#define PROATM_CFG_RCTSIZE_16384_ENTRIES 0x00020000
#define PROATM_CFG_RCTSIZE_512_ENTRIES   0x00030000

#define PROATM_CFG_RXINT_NOINT   0x00000000
#define PROATM_CFG_RXINT_NODELAY 0x00001000
#define PROATM_CFG_RXINT_2800CLK 0x00002000
#define PROATM_CFG_RXINT_4F00CLK 0x00003000
#define PROATM_CFG_RXINT_7400CLK 0x00004000


/* Configuration Register */
#define PROATM_BASIC_CFG  ( \
        PROATM_CFG_RXPATH | \
                PROATM_CFG_RSQSIZE | \
                PROATM_CFG_RXINT_NODELAY | \
                PROATM_CFG_TMRROIE  | \
                PROATM_CFG_TXEN | \
                PROATM_CFG_TXIE | \
                PROATM_CFG_RSQAFIE | \
                PROATM_CFG_TSQFIE | \
                PROATM_CFG_FBIE | \
                PROATM_CFG_PHYIE )

#ifdef  PROATM_RCQ_SUPPORT
#define PROATM_RCQ_CFG ( \
        PROATM_CFG_ICACCEPT | \
        PROATM_CFG_RAWIE | \
        PROATM_CFG_IGNOREGFC )
#else
#define PROATM_RCQ_CFG 0
#endif

#define PROATM_DEFAULT_CFG (PROATM_BASIC_CFG | PROATM_RCQ_CFG)

/* SAR STATUS bits ********************************************************/

#define PROATM_STAT_FRAC3_MASK 0xF0000000
#define PROATM_STAT_FRAC2_MASK 0x0F000000
#define PROATM_STAT_FRAC1_MASK 0x00F00000
#define PROATM_STAT_FRAC0_MASK 0x000F0000
#define PROATM_STAT_TSIF       0x00008000   /* Transmit Status Queue Indicator */
#define PROATM_STAT_TXICP      0x00004000   /* Transmit Incomplete PDU */
#define PROATM_STAT_TSQF       0x00001000   /* Transmit Status Queue Full */
#define PROATM_STAT_TMROF      0x00000800   /* Timer Overflow */
#define PROATM_STAT_PHYI       0x00000400   /* PHY Device Interrupt */
#define PROATM_STAT_CMDBZ      0x00000200   /* Command Busy */
#define PROATM_STAT_FBQ3A      0x00000100   /* Free Buffer Queue Attention */
#define PROATM_STAT_FBQ2A      0x00000080   /* Free Buffer Queue Attention */
#define PROATM_STAT_RSQF       0x00000040   /* Receive Status Queue Full */
#define PROATM_STAT_EOPDU      0x00000020   /* End of PDU */
#define PROATM_STAT_RAWCF      0x00000010   /* Raw Cell Flag */
#define PROATM_STAT_FBQ1A      0x00000008   /* Free Buffer Queue Attention */
#define PROATM_STAT_FBQ0A      0x00000004   /* Free Buffer Queue Attention */
#define PROATM_STAT_RSQAF      0x00000002   /* Receive Status Queue Almost Full */

/* SAR TCMDQ Register *****************************************************/

#define PROATM_START                0x01000000 
#define PROATM_UPD_LACR             0x02000000
#define PROATM_START_UPD_LACR       0x03000000
#define PROATM_UPD_INIT_ER          0x04000000
#define PROATM_HALT                 0x05000000

/* GP Register Bits *************************************************/
#define PROATM_GP_EECLK     (1<<2)
#define PROATM_GP_EECS      (1<<1)
#define PROATM_GP_EEDO      1
#define PROATM_GP_EEDI      (1<<16)
                                                           
/* PROATM free buf. queues ***************************************************/

/* registers #34-#37 */
#define PROATM_FBQPR_MASK      0x000003FF 
#define PROATM_FBQPW_MASK      0x03FF0000

#define diff(fbqp)  (int) ((int)((((fbqp) & PROATM_FBQPW_MASK)>>16) - ((fbqp) & PROATM_FBQPR_MASK))/2)
/* number of free buffer descriptors (max=512) */
#define proatm_fbqc_get(fbqp)  (diff(fbqp) >= 0 ? diff(fbqp) : 0x200 + diff(fbqp))

/* #defines which depend on other #defines ************************************/

#if (PROATM_RSQSIZE == 2048)
#define PROATM_CFG_RSQSIZE PROATM_CFG_RSQSIZE_2048
#elif (PROATM_RSQSIZE == 4096)
#define PROATM_CFG_RSQSIZE PROATM_CFG_RSQSIZE_4096
#elif (PROATM_RSQSIZE == 8192)
#define PROATM_CFG_RSQSIZE PROATM_CFG_RSQSIZE_8192
#else
#error PROATM_RSQSIZE is incorrect in proatm.h
#endif /* PROATM_RSQSIZE */


#ifdef RCQ_SUPPORT
#define PROATM_CFG_RAWIE_OPT PROATM_CFG_RAWIE
#else
#define PROATM_CFG_RAWIE_OPT 0x00000000
#endif /* RCQ_SUPPORT */

/* PCI stuff ******************************************************************/

#ifndef PCI_VENDOR_ID_IDT
#define PCI_VENDOR_ID_IDT 0x111D
#endif /* PCI_VENDOR_ID_IDT */

#ifndef PCI_DEVICE_ID_IDT_IDT77252
#define PCI_DEVICE_ID_IDT_IDT77252 0x0003
#endif
#ifndef PCI_DEVICE_ID_IDT_IDT77V252
#define PCI_DEVICE_ID_IDT_IDT77V252 0x0004
#endif


/* Device driver structures ***************************************************/


typedef struct tsq_info
{
   u8                   *org;
   dma_addr_t           org_pa;
   proatm_tsi           *base;
   dma_addr_t           base_pa;
   proatm_tsi           *next;
} tsq_info;


typedef struct scq_info
{
   u8                   *org;
   dma_addr_t           org_pa;
   proatm_scqe          *base;
   dma_addr_t           base_pa;
   proatm_scqe          *last;
   proatm_scqe          *next;
   volatile proatm_scqe *tail;          /* Not related to the SAR register */
   int                  scq_type;       /* CBR_SCQ, UBR_SCQ, VBR_SCQ or ABR_SCQ */
   struct sk_buff       **skb;          /* Pointer to an array of pointers to the sk_buffs used for tx */
   struct sk_buff_head  waiting;        /* head of queue of skb's waiting for transmission */
   u32                  scd;            /* SRAM address of the corresponding SCD */
   int                  tbd_count;      /* Only meaningful on variable rate */
   volatile u32         full;           /* SCQ full indicator */
   spinlock_t           lock;           /* SCQ spinlock */
} scq_info;

#define MAX_TBD_COUNT   256

#define UBR_SCQ  1
#define CBR_SCQ  2
#define VBR_SCQ  3
#define ABR_SCQ  4

typedef struct rsq_info
{
   u8                   *org;
   dma_addr_t           org_pa;
   proatm_rsqe          *base;
   dma_addr_t           base_pa;
   proatm_rsqe          *next;
   proatm_rsqe          *last;
} rsq_info;


typedef struct vc_map
{
   struct atm_vcc       *tx_vcc;
   struct atm_vcc       *rx_vcc;
   struct sk_buff       *rx_sdu_head;   /* First skb of the received SDU */
   struct sk_buff       *rx_sdu_tail;   /* Current skb of the received SDU */
   scq_info             *scq;           /* To keep track of the SCQ */
   u32                  adr_scd;        /* SRAM address of the corresponding SCD */
   u32                  bufcnt;         /* Number of skbuffs in the current SDU */
   u32                  totlen;         /* Total len of the current SDU */
   int                  tbd_count;
   u8                   lacr;
   u8                   init_er;
   volatile u8          tx:1;           /* TX vc? */
   volatile u8          rx:1;           /* RX vc? */
   volatile u8          active:1;       /* the connection is active */
   volatile u8          oam_cc:1;       /* oam continuity check is enabled */
   volatile u8          closing:1;      /* this vc is closing */
} vc_map;

typedef struct fb_info
{
         struct sk_buff     *skb_ptr;           /* free skb pointer */
         int                            sar_count;              /* sar usage count */
} fb_info;

#define FB_MAXDQC       (MAX_B1 * 3)

struct proatm_skb_cb {
    u32     index;
    dma_addr_t paddr;
    int     buflen;
    u32     flags;    
};

#define PROATM_SKB(skb)  ((struct proatm_skb_cb *)(ATM_SKB(skb)+1))

/*
 * FIX #1b: proatm_skb_cb is stored *after* struct atm_skb_data inside the
 * 48-byte skb->cb[] scratch area. struct atm_skb_data has grown over the
 * years and proatm_skb_cb just grew by 4 bytes (u32 -> dma_addr_t), so make
 * the kernel prove at build time that both still fit. If this fires, move
 * index/paddr/buflen out of skb->cb and into card->fb_table[] instead.
 */
static_assert(sizeof(struct atm_skb_data) + sizeof(struct proatm_skb_cb)
              <= sizeof_field(struct sk_buff, cb),
              "proatm_skb_cb does not fit in skb->cb[]");

typedef struct proatm_dev
{
   int                  index;                          /* Card ID to the device driver */
   char                 name[16];                       /* card name */
   int					dead;
   u32                  sram_size;                      /* In k x 32bit words. 32 or 128 */
   void __iomem         *membase;
   void __iomem         *fbq[2];
   u32                  fbqc[2];                                                /* SAR number of buffers in the free buffer queues */
   u32                  max_pcr;
   u32                  rct_size;                       /* Number of entries */
   u32                  scd_size;
   u32                  tst_num;                          
   u32                  vpibits;
   u32                  vcibits;
   u32                  maxvpi;
   u32                  maxvci;
   u32                  vpm;                            /* MASK register value */
   u32                  rct;                            /* SRAM address of RCT */
   u32                  rate;                           /* SRAM address of Rate Table */
   u32                  tst;                            /* SRAM address of TST */
   u32                  dtst;                           /* SRAM address of ABR-VBR TST (DTST)*/
   u32                  scd;                            /* SRAM address of SCDs */
   u32                  scd_ubr0;                       /* SRAM address of no pcr SCD */
   u32                  rxfifo;                         /* SRAM address of receive fifo */
   struct pci_dev       *pcidev;
   struct atm_dev       *atmdev;
   tsq_info             tsq;
   rsq_info             rsq;
   scq_info             *scq0;                          /* UBR SCQ for unspecified PCR */
   volatile int         fbie;                           /* free buf. queue int. enabled */
   volatile int         tst_free_entries;
#ifdef PROATM_OAM_SUPPORT
   struct work_struct   oam_w;
   struct sk_buff_head  oam_tq;                         /* oam transmit queue */   
#endif
   vc_map               *vcmap;                               
   vc_map               *tste2vc[PROATM_TST_SIZE_MAX];  /* table of VC descriptors*/ 
   vc_map               *scd2vc[PROATM_SCD_NUM];   
   struct sk_buff       *rcbuf;                         /* Current raw cell buffer */
   int                  fb_count;                       /* Max index of fb_table */
   int                  fb_dequeue_count;               /* used for free buffer management */
   int                  fb_info_valid;                  /* used for free buffer management */
   fb_info              fb_table[MAX_B1];               /* table of free buffer descriptors */
   proatm_rcqe          *raw_ch;                        /* Raw cell queue head */
   u32                  raw_ch_pa;
   u32                  *raw_hnd;                       /* raw cell queue tail pointer and rawcell handle */
   dma_addr_t           raw_hnd_pa;						/* physical adress */
   size_t               raw_hnd_size;  					/* NEW: size passed to dma_alloc_coherent,must be reused verbatim on free */
   u32                  intcnt;                         /* Interrupt counter */
   spinlock_t           int_lock;                       /* Interrupt lock */
   spinlock_t           res_lock;                       /* Card resource lock */
} proatm_dev;


#endif /* _LINUX_PROATM_H */
