/**HEADER********************************************************************
*
* Copyright (c) 2009 Freescale Semiconductor;
* All Rights Reserved
*
***************************************************************************
*
* THIS SOFTWARE IS PROVIDED BY FREESCALE "AS IS" AND ANY EXPRESSED 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 FREESCALE OR ITS 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.
*
**************************************************************************
*
* $FileName: usbprv_fs.h$
* $Version : 3.4.1.0$
* $Date    : Sep-15-2009$
*
* Comments:
*
*   This file contains the private defines, externs and data structure
*   definitions required by the Full Speed USB Device driver.
*
*END************************************************************************/

#ifndef __usbprv_fs_h__
#define __usbprv_fs_h__ 1

#include "devapi.h"

#define  MAX_XDS_FOR_TR_CALLS                (32) 
#define  MAX_USB_DEVICES                     (1)
#define  USB_MAX_ENDPOINTS                   (16) 
#define ODD_BUFF                             (1)
#define EVEN_BUFF                            (0)


typedef struct xd_struct 
{
   uchar        EP_NUM;          /* Endpoint number */
   uchar        BDIRECTION;      /* Direction : Send/Receive */
   uint_8       EP_TYPE;         /* Type of the endpoint: Ctrl, Isoch, Bulk, 
                                 ** Int 
                                 */
   uchar        BSTATUS;         /* Current transfer status */
   uchar_ptr    WSTARTADDRESS;   /* Address of first byte */
   uint_32      WTOTALLENGTH;    /* Number of bytes to send/recv */
   uint_32      WSOFAR;          /* Number of bytes recv'd so far */
   uint_16      WMAXPACKETSIZE;  /* Max Packet size */
   boolean     	DONT_ZERO_TERMINATE;

   boolean 		ZERO_PACKET;
   uint_32      WPOSITION;  	 /* current position of the buffer */
   uint_32	   	FIFO_SIZE;		 /* To keep track of FIFO length for this ep */
   uint_32	   	IN_FIFO_ADDR;	 /* To keep track of FIFO start address for this ep */
   uint_32	   	OUT_FIFO_ADDR;	 /* To keep track of FIFO start address for this ep */   
   uint_8	   	VECTOR;			 /* Vector of this endpoint */
   uchar 	   	SETUP[8];		 /* Just maintain SETUP packet */

   pointer 		MY_XDPTR;		 /* This will save the xd_ptr send by API during
   								 **	send/ recv request 
   								 */
   uchar_ptr	OUT_TEMP_BUFFER; /* This is required during OUT interrupt to store 
   								 **	OUT data 
   								 */
   boolean      IS_SETUP_PACKET; /* To identify SETUP packet. this is required when 
   								 ** there is setup packet and upper driver does not want 
   								 ** to send the data in the	 data phase, we still need to 
   								 **	set the CMD_OVER to indicate that the processing of 
   								 **	class/vendor specific request is completed.
   								 */
   uint_16					PENDING_XD;	/* counter */
   
   SCRATCH_STRUCT_PTR SCRATCH_PTR;
} XD_STRUCT, _PTR_ XD_STRUCT_PTR;

typedef struct _usb_xd_queue
{
   struct xd_struct _PTR_ xd_head_ptr;
   struct xd_struct _PTR_ xd_tail_ptr;
} USB_XD_QUEUE, _PTR_ USB_XD_QUEUE_PTR;

typedef struct _usb_ep_info_struct
{
   USB_XD_QUEUE xd_queue_send;  /* FIFO queue for all XDs on this endpoint */   
   USB_XD_QUEUE xd_queue_recv;
   uint_8 type;
   uint_8 direction; /* for _usb_device_call_service */
   uint_16 max_packet_size;
   uint_16 fifo_length;
   
   uint_8 tx_data0;
   uint_8 rx_data0;
   
   uint_8 tx_buf_odd;
   uint_8 rx_buf_odd;   /* next buffer is odd */
   uint_8_ptr data_buffer;
   uint_16 endpoint_status;
   boolean stall_flag;
   /* Endpoint initialization flag for both direction */
   boolean ep_init_flag[2]; 
   uint_32 save_recv_addr;
} USB_EP_INFO_STRUCT, _PTR_ USB_EP_INFO_STRUCT_PTR;

/* The USB Device State Structure */
typedef struct _usb_device_state_struct 
{
   pointer                          DEV_PTR;             /* Device Controller 
                                                         ** Register base 
                                                         ** address 
                                                         */
   pointer                          CALLBACK_STRUCT_PTR;
   
   SERVICE_STRUCT_PTR               SERVICE_HEAD_PTR;       /* Head struct 
                                                         ** address of 
                                                         ** registered services 
                                                         */
   XD_STRUCT_PTR                    TEMP_XD_PTR;         /* Temp xd for ep init */
   XD_STRUCT_PTR                    XD_BASE;
   XD_STRUCT_PTR                    XD_HEAD;             /* Head Transaction 
                                                         ** descriptors 
                                                         */
   XD_STRUCT_PTR                    XD_TAIL;             /* Tail Transaction 
                                                         ** descriptors 
                                                         */
   XD_STRUCT_PTR                    PENDING_XD_PTR;      /* pending transfer */
   uint_32                          XD_ENTRIES;

   SCRATCH_STRUCT_PTR               XD_SCRATCH_STRUCT_BASE;
   SCRATCH_STRUCT_PTR               SCRATCH_STRUCT_BASE;
   
   uint_16                          USB_STATE;
   uint_16                          USB_DEVICE_STATE;
   uint_16                          USB_SOF_COUNT;
   uint_16                          ERRORS;
   uint_16                          USB_DEV_STATE_B4_SUSPEND;
   uint_8                           DEV_NUM;             /* USB device number 
                                                         ** on the board 
                                                         */
   uint_8                           DEV_VEC;             /* Interrupt vector 
                                                         ** number for USB 
                                                         */
   uint_8                           SPEED;               /* Low Speed, 
                                                         ** High Speed, 
                                                         ** Full Speed 
                                                         */
   uint_8                           MAX_ENDPOINTS;       /* Max endpoints
                                                         ** supported by this
                                                         ** device
                                                         */
                                                         
   uint_16                          USB_CURR_CONFIG;                                                         
   uint_8                           DEVICE_ADDRESS;
   USB_EP_INFO_STRUCT               EP_INFO[USB_MAX_ENDPOINTS];
} USB_DEV_STATE_STRUCT, _PTR_ USB_DEV_STATE_STRUCT_PTR;

#define USB_XD_QADD(head,tail,XD)            \
   if ((head) == NULL) {                     \
      (head) = (XD);                         \
   } else {                                  \
      (tail)->SCRATCH_PTR->PRIVATE = (XD);   \
   } /* Endif */                             \
   (tail) = (XD);                            \
   (XD)->SCRATCH_PTR->PRIVATE = NULL
   
#define USB_XD_QGET(head,tail,XD)                              \
   (XD) = (head);                                              \
   if (head) {                                                 \
      (head) = (XD_STRUCT_PTR)((head)->SCRATCH_PTR->PRIVATE);  \
      if ((head) == NULL) {                                    \
         (tail) = NULL;                                        \
      } /* Endif */                                            \
   } /* Endif */
  
#define USB_XD_QUEUE_INIT(xd_queue_ptr)                        \
   (xd_queue_ptr)->xd_head_ptr = 0x0;                          \
   (xd_queue_ptr)->xd_tail_ptr = 0x0

#define USB_XD_QUEUE_ENQUEUE(xd_queue_ptr, xd_ptr)  \
   USB_XD_QADD ((xd_queue_ptr)->xd_head_ptr, (xd_queue_ptr)->xd_tail_ptr, (xd_ptr))
   
#define USB_XD_QUEUE_DEQUEUE(xd_queue_ptr, xd_ptr_ptr)  \
   USB_XD_QGET ((xd_queue_ptr)->xd_head_ptr, (xd_queue_ptr)->xd_tail_ptr, *(xd_ptr_ptr))
   
#define USB_XD_QUEUE_ENQUEUE_SAFE(xd_queue_ptr, xd_ptr)  \
   _int_disable ();  \
   USB_XD_QUEUE_ENQUEUE (xd_queue_ptr, xd_ptr); \
   _int_enable ();

#define USB_XD_QUEUE_DEQUEUE_SAFE(xd_queue_ptr, xd_ptr)  \
   _int_disable ();  \
   USB_XD_QUEUE_DEQUEUE (xd_queue_ptr, xd_ptr); \
   _int_enable ();

#define USB_XD_QUEUE_GET_HEAD(xd_queue_ptr, xd_ptr_ptr)  \
   *(xd_ptr_ptr) = (xd_queue_ptr)->xd_head_ptr

#define USB_XD_QUEUE_GET_TAIL(xd_queue_ptr, xd_ptr_ptr)  \
   *(xd_ptr_ptr) = (xd_queue_ptr)->xd_tail_ptr

/***************************************
**
** Prototypes
**
*/
extern void _usb_device_free_XD
(
	_usb_device_handle  handle,
	/* [IN] the dTD to enqueue */
	pointer  xd_ptr
);

#ifdef __cplusplus
extern "C" {
#endif

#ifdef __cplusplus
}
#endif

#endif