blob: 5c7972f91ef648ab58c99e168309dce73abbe9f3 [file] [log] [blame]
/* Cypress West Bridge API header file (cyaslowlevel.h)
## ===========================
## Copyright (C) 2010 Cypress Semiconductor
##
## 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; either version 2
## of the License, or (at your option) any later version.
##
## This program 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 this program; if not, write to the Free Software
## Foundation, Inc., 51 Franklin Street
## Fifth Floor, Boston, MA 02110-1301, USA.
## ===========================
*/
#ifndef _INCLUDED_CYASLOWLEVEL_H_
#define _INCLUDED_CYASLOWLEVEL_H_
/*@@Low Level Communications
Summary
The low level communications module is responsible for
communications between the West Bridge device and the P
port processor. Communications is organized as a series
of requests and subsequent responses. For each request
there is a one and only one response. Requests may go
from the West Bridge device to the P port processor, or
from the P Port processor to the West Bridge device.
Description
Requests are issued across what is called a context. A
context is a single channel of communications from one
processor to another processor. There can be only a single
request outstanding on a context at a given time. Contexts
are used to identify subsystems that can only process a
single request at a time, but are independent of other
contexts in the system. For instance, there is a context
for communicating storage commands from the P port processor
to the West Bridge device. There is also a context for
communicating USB commands from the P port processor to the
West Bridge device.
Requests and responses are identical with the exception of
the type bit in the request/response header. If the type
bit is one, the packet is a request. If this bit is zero,
the packet is a response. Also encoded within the header of
the request/response is the code. The code is a command
code for a request, or a response code for a response. For
a request, the code is a function of the context. The code
0 has one meaning for the storage context and a different
meaning for the USB context. The code is treated differently
in the response. If the code in the response is less than 16,
then the meaning of the response is global across all
contexts. If the response is greater than or equal to 16,
then the response is specific to the associated context.
Requests and responses are transferred between processors
through the mailbox registers. It may take one or more cycles
to transmit a complete request or response. The context is
encoded into each cycle of the transfer to insure the
receiving processor can route the data to the appropriate
context for processing. In this way, the traffic from multiple
contexts can be multiplexed into a single data stream through
the mailbox registers by the sending processor, and
demultiplexed from the mailbox registers by the receiving
processor.
* Firmware Assumptions *
The firmware assumes that mailbox contents will be consumed
immediately. Therefore for multi-cycle packets, the data is
sent in a tight polling loop from the firmware. This implies
that the data must be read from the mailbox register on the P
port side and processed immediately or performance of the
firmware will suffer. In order to insure this is the case,
the data from the mailboxes is read and stored immediately
in a per context buffer. This occurs until the entire packet
is received at which time the request packet is processed.
Since the protocol is designed to allow for only one
outstanding packet at a time, the firmware can never be in a
position of waiting on the mailbox registers while the P port
is processing a request. Only after the response to the
previous request is sent will another request be sent.
*/
#include "cyashal.h"
#include "cyasdevice.h"
#include "cyas_cplus_start.h"
/*
* Constants
*/
#define CY_AS_REQUEST_RESPONSE_CODE_MASK (0x00ff)
#define CY_AS_REQUEST_RESPONSE_CONTEXT_MASK (0x0F00)
#define CY_AS_REQUEST_RESPONSE_CONTEXT_SHIFT (8)
#define CY_AS_REQUEST_RESPONSE_TYPE_MASK (0x4000)
#define CY_AS_REQUEST_RESPONSE_LAST_MASK (0x8000)
#define CY_AS_REQUEST_RESPONSE_CLEAR_STR_FLAG (0x1000)
/*
* These macros extract the data from a 16 bit value
*/
#define cy_as_mbox_get_code(c) \
((uint8_t)((c) & CY_AS_REQUEST_RESPONSE_CODE_MASK))
#define cy_as_mbox_get_context(c) \
((uint8_t)(((c) & CY_AS_REQUEST_RESPONSE_CONTEXT_MASK) \
>> CY_AS_REQUEST_RESPONSE_CONTEXT_SHIFT))
#define cy_as_mbox_is_last(c) \
((c) & CY_AS_REQUEST_RESPONSE_LAST_MASK)
#define cy_as_mbox_is_request(c) \
(((c) & CY_AS_REQUEST_RESPONSE_TYPE_MASK) != 0)
#define cy_as_mbox_is_response(c) \
(((c) & CY_AS_REQUEST_RESPONSE_TYPE_MASK) == 0)
/*
* These macros (not yet written) pack data into or extract data
* from the m_box0 field of the request or response
*/
#define cy_as_ll_request_response__set_code(req, code) \
((req)->box0 = \
((req)->box0 & ~CY_AS_REQUEST_RESPONSE_CODE_MASK) | \
(code & CY_AS_REQUEST_RESPONSE_CODE_MASK))
#define cy_as_ll_request_response__get_code(req) \
cy_as_mbox_get_code((req)->box0)
#define cy_as_ll_request_response__set_context(req, context) \
((req)->box0 |= ((context) << \
CY_AS_REQUEST_RESPONSE_CONTEXT_SHIFT))
#define cy_as_ll_request_response__set_clear_storage_flag(req) \
((req)->box0 |= CY_AS_REQUEST_RESPONSE_CLEAR_STR_FLAG)
#define cy_as_ll_request_response__get_context(req) \
cy_as_mbox_get_context((req)->box0)
#define cy_as_ll_request_response__is_last(req) \
cy_as_mbox_is_last((req)->box0)
#define CY_an_ll_request_response___set_last(req) \
((req)->box0 |= CY_AS_REQUEST_RESPONSE_LAST_MASK)
#define cy_as_ll_request_response__is_request(req) \
cy_as_mbox_is_request((req)->box0)
#define cy_as_ll_request_response__set_request(req) \
((req)->box0 |= CY_AS_REQUEST_RESPONSE_TYPE_MASK)
#define cy_as_ll_request_response__set_response(req) \
((req)->box0 &= ~CY_AS_REQUEST_RESPONSE_TYPE_MASK)
#define cy_as_ll_request_response__is_response(req) \
cy_as_mbox_is_response((req)->box0)
#define cy_as_ll_request_response__get_word(req, offset) \
((req)->data[(offset)])
#define cy_as_ll_request_response__set_word(req, offset, \
value) ((req)->data[(offset)] = value)
typedef enum cy_as_remove_request_result_t {
cy_as_remove_request_sucessful,
cy_as_remove_request_in_transit,
cy_as_remove_request_not_found
} cy_as_remove_request_result_t;
/* Summary
Start the low level communications module
Description
*/
cy_as_return_status_t
cy_as_ll_start(
cy_as_device *dev_p
);
cy_as_return_status_t
cy_as_ll_stop(
cy_as_device *dev_p
);
cy_as_ll_request_response *
cy_as_ll_create_request(
cy_as_device *dev_p,
uint16_t code,
uint8_t context,
/* Length of the request in 16 bit words */
uint16_t length
);
void
cy_as_ll_init_request(
cy_as_ll_request_response *req_p,
uint16_t code,
uint16_t context,
uint16_t length);
void
cy_as_ll_init_response(
cy_as_ll_request_response *req_p,
uint16_t length);
void
cy_as_ll_destroy_request(
cy_as_device *dev_p,
cy_as_ll_request_response *);
cy_as_ll_request_response *
cy_as_ll_create_response(
cy_as_device *dev_p,
/* Length of the request in 16 bit words */
uint16_t length
);
cy_as_remove_request_result_t
cy_as_ll_remove_request(
cy_as_device *dev_p,
cy_as_context *ctxt_p,
cy_as_ll_request_response *req_p,
cy_bool force
);
void
cy_as_ll_remove_all_requests(cy_as_device *dev_p,
cy_as_context *ctxt_p);
void
cy_as_ll_destroy_response(
cy_as_device *dev_p,
cy_as_ll_request_response *);
cy_as_return_status_t
cy_as_ll_send_request(
/* The West Bridge device */
cy_as_device *dev_p,
/* The request to send */
cy_as_ll_request_response *req,
/* Storage for a reply, must be sure it is of sufficient size */
cy_as_ll_request_response *resp,
/* If true, this is a sync request */
cy_bool sync,
/* Callback to call when reply is received */
cy_as_response_callback cb
);
cy_as_return_status_t
cy_as_ll_send_request_wait_reply(
/* The West Bridge device */
cy_as_device *dev_p,
/* The request to send */
cy_as_ll_request_response *req,
/* Storage for a reply, must be sure it is of sufficient size */
cy_as_ll_request_response *resp
);
/* Summary
This function registers a callback function to be called when a
request arrives on a given context.
Description
Returns
* CY_AS_ERROR_SUCCESS
*/
extern cy_as_return_status_t
cy_as_ll_register_request_callback(
cy_as_device *dev_p,
uint8_t context,
cy_as_response_callback cb
);
/* Summary
This function packs a set of bytes given by the data_p pointer
into a request, reply structure.
*/
extern void
cy_as_ll_request_response__pack(
/* The destintation request or response */
cy_as_ll_request_response *req,
/* The offset of where to pack the data */
uint32_t offset,
/* The length of the data to pack in bytes */
uint32_t length,
/* The data to pack */
void *data_p
);
/* Summary
This function unpacks a set of bytes from a request/reply
structure into a segment of memory given by the data_p pointer.
*/
extern void
cy_as_ll_request_response__unpack(
/* The source of the data to unpack */
cy_as_ll_request_response *req,
/* The offset of the data to unpack */
uint32_t offset,
/* The length of the data to unpack in bytes */
uint32_t length,
/* The destination of the unpack operation */
void *data_p
);
/* Summary
This function sends a status response back to the West Bridge
device in response to a previously send request
*/
extern cy_as_return_status_t
cy_as_ll_send_status_response(
/* The West Bridge device */
cy_as_device *dev_p,
/* The context to send the response on */
uint8_t context,
/* The success/failure code to send */
uint16_t code,
/* Flag to clear wait on storage context */
uint8_t clear_storage);
/* Summary
This function sends a response back to the West Bridge device.
Description
This function sends a response back to the West Bridge device.
The response is sent on the context given by the 'context'
variable. The code for the response is given by the 'code'
argument. The data for the response is given by the data and
length arguments.
*/
extern cy_as_return_status_t
cy_as_ll_send_data_response(
/* The West Bridge device */
cy_as_device *dev_p,
/* The context to send the response on */
uint8_t context,
/* The response code to use */
uint16_t code,
/* The length of the data for the response */
uint16_t length,
/* The data for the response */
void *data
);
/* Summary
This function removes any requests of the given type
from the given context.
Description
This function removes requests of a given type from the
context given via the context number.
*/
extern cy_as_return_status_t
cy_as_ll_remove_ep_data_requests(
/* The West Bridge device */
cy_as_device *dev_p,
cy_as_end_point_number_t ep
);
#include "cyas_cplus_end.h"
#endif /* _INCLUDED_CYASLOWLEVEL_H_ */