blob: 81ffea79d00895990661afa20af2ba05263b5cef [file] [log] [blame]
/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __DBUS_H__
#define __DBUS_H__
#ifdef BCMDBG
#define DBUSERR(args) do { if (net_ratelimit()) printf args; } while (0)
#define DBUSTRACE(args)
#define DBUSDBGLOCK(args)
#else
#define DBUSTRACE(args)
#define DBUSERR(args)
#define DBUSDBGLOCK(args)
#endif
enum {
DBUS_OK = 0,
DBUS_ERR = -200,
DBUS_ERR_TIMEOUT,
DBUS_ERR_DISCONNECT,
DBUS_ERR_NODEVICE,
DBUS_ERR_UNSUPPORTED,
DBUS_ERR_PENDING,
DBUS_ERR_NOMEM,
DBUS_ERR_TXFAIL,
DBUS_ERR_TXTIMEOUT,
DBUS_ERR_TXDROP,
DBUS_ERR_RXFAIL,
DBUS_ERR_RXDROP,
DBUS_ERR_TXCTLFAIL,
DBUS_ERR_RXCTLFAIL,
DBUS_ERR_REG_PARAM,
DBUS_STATUS_CANCELLED
};
#define ERR_CBMASK_TXFAIL 0x00000001
#define ERR_CBMASK_RXFAIL 0x00000002
#define ERR_CBMASK_ALL 0xFFFFFFFF
#define DBUS_CBCTL_WRITE 0
#define DBUS_CBCTL_READ 1
#define DBUS_TX_RETRY_LIMIT 3 /* retries for failed txirb */
#define DBUS_TX_TIMEOUT_INTERVAL 250 /* timeout for txirb complete, in ms */
#define DBUS_BUFFER_SIZE_TX 5000
#define DBUS_BUFFER_SIZE_RX 5000
#define DBUS_BUFFER_SIZE_TX_NOAGG 2048
#define DBUS_BUFFER_SIZE_RX_NOAGG 2048
/* DBUS types */
enum {
DBUS_USB,
DBUS_SDIO,
DBUS_SPI,
DBUS_UNKNOWN
};
enum dbus_state {
DBUS_STATE_DL_PENDING,
DBUS_STATE_DL_DONE,
DBUS_STATE_UP,
DBUS_STATE_DOWN,
DBUS_STATE_PNP_FWDL,
DBUS_STATE_DISCONNECT
};
enum dbus_pnp_state {
DBUS_PNP_DISCONNECT,
DBUS_PNP_SLEEP,
DBUS_PNP_RESUME
};
typedef enum _DEVICE_SPEED {
INVALID_SPEED = -1,
LOW_SPEED = 1, /* USB 1.1: 1.5 Mbps */
FULL_SPEED, /* USB 1.1: 12 Mbps */
HIGH_SPEED, /* USB 2.0: 480 Mbps */
SUPER_SPEED, /* USB 3.0: 4.8 Gbps */
} DEVICE_SPEED;
typedef struct {
int bustype;
int vid;
int pid;
int devid;
int chiprev; /* chip revsion number */
int mtu;
int nchan; /* Data Channels */
} dbus_attrib_t;
/* FIX: Account for errors related to DBUS;
* Let upper layer account for packets/bytes
*/
typedef struct {
u32 rx_errors;
u32 tx_errors;
u32 rx_dropped;
u32 tx_dropped;
} dbus_stats_t;
/*
* Configurable BUS parameters
*/
typedef struct {
bool rxctl_deferrespok;
} dbus_config_t;
struct dbus_callbacks;
struct exec_parms;
typedef void *(*probe_cb_t) (void *arg, const char *desc, u32 bustype,
u32 hdrlen);
typedef void (*disconnect_cb_t) (void *arg);
typedef void *(*exec_cb_t) (struct exec_parms *args);
/* Client callbacks registered during dbus_attach() */
typedef struct dbus_callbacks {
void (*send_complete) (void *cbarg, void *info, int status);
void (*recv_buf) (void *cbarg, u8 *buf, int len);
void (*recv_pkt) (void *cbarg, void *pkt);
void (*txflowcontrol) (void *cbarg, bool onoff);
void (*errhandler) (void *cbarg, int err);
void (*ctl_complete) (void *cbarg, int type, int status);
void (*state_change) (void *cbarg, int state);
void *(*pktget) (void *cbarg, uint len, bool send);
void (*pktfree) (void *cbarg, void *p, bool send);
} dbus_callbacks_t;
struct dbus_pub;
struct bcmstrbuf;
struct dbus_irb;
struct dbus_irb_rx;
struct dbus_irb_tx;
struct dbus_intf_callbacks;
typedef struct {
void *(*attach) (struct dbus_pub *pub, void *cbarg,
struct dbus_intf_callbacks *cbs);
void (*detach) (struct dbus_pub *pub, void *bus);
int (*up) (void *bus);
int (*down) (void *bus);
int (*send_irb) (void *bus, struct dbus_irb_tx *txirb);
int (*recv_irb) (void *bus, struct dbus_irb_rx *rxirb);
int (*cancel_irb) (void *bus, struct dbus_irb_tx *txirb);
int (*send_ctl) (void *bus, u8 *buf, int len);
int (*recv_ctl) (void *bus, u8 *buf, int len);
int (*get_stats) (void *bus, dbus_stats_t *stats);
int (*get_attrib) (void *bus, dbus_attrib_t *attrib);
int (*pnp) (void *bus, int event);
int (*remove) (void *bus);
int (*resume) (void *bus);
int (*suspend) (void *bus);
int (*stop) (void *bus);
int (*reset) (void *bus);
/* Access to bus buffers directly */
void *(*pktget) (void *bus, int len);
void (*pktfree) (void *bus, void *pkt);
int (*iovar_op) (void *bus, const char *name, void *params, int plen,
void *arg, int len, bool set);
void (*dump) (void *bus, struct bcmstrbuf *strbuf);
int (*set_config) (void *bus, dbus_config_t *config);
int (*get_config) (void *bus, dbus_config_t *config);
bool(*device_exists) (void *bus);
bool(*dlneeded) (void *bus);
int (*dlstart) (void *bus, u8 *fw, int len);
int (*dlrun) (void *bus);
bool(*recv_needed) (void *bus);
void *(*exec_rxlock) (void *bus, exec_cb_t func,
struct exec_parms *args);
void *(*exec_txlock) (void *bus, exec_cb_t func,
struct exec_parms *args);
int (*tx_timer_init) (void *bus);
int (*tx_timer_start) (void *bus, uint timeout);
int (*tx_timer_stop) (void *bus);
int (*sched_dpc) (void *bus);
int (*lock) (void *bus);
int (*unlock) (void *bus);
int (*sched_probe_cb) (void *bus);
int (*shutdown) (void *bus);
int (*recv_stop) (void *bus);
int (*recv_resume) (void *bus);
/* Add from the bottom */
} dbus_intf_t;
typedef struct dbus_pub {
struct osl_info *osh;
dbus_stats_t stats;
dbus_attrib_t attrib;
enum dbus_state busstate;
DEVICE_SPEED device_speed;
int ntxq, nrxq, rxsize;
void *bus;
struct shared_info *sh;
} dbus_pub_t;
#define BUS_INFO(bus, type) (((type *) bus)->pub->bus)
/*
* Public Bus Function Interface
*/
extern int dbus_register(int vid, int pid, probe_cb_t prcb,
disconnect_cb_t discb, void *prarg, void *param1,
void *param2);
extern int dbus_deregister(void);
extern const dbus_pub_t *dbus_attach(struct osl_info *osh, int rxsize, int nrxq,
int ntxq, void *cbarg,
dbus_callbacks_t *cbs,
struct shared_info *sh);
extern void dbus_detach(const dbus_pub_t *pub);
extern int dbus_up(const dbus_pub_t *pub);
extern int dbus_down(const dbus_pub_t *pub);
extern int dbus_stop(const dbus_pub_t *pub);
extern int dbus_shutdown(const dbus_pub_t *pub);
extern void dbus_flowctrl_rx(const dbus_pub_t *pub, bool on);
extern int dbus_send_buf(const dbus_pub_t *pub, u8 *buf, int len,
void *info);
extern int dbus_send_pkt(const dbus_pub_t *pub, void *pkt, void *info);
extern int dbus_send_ctl(const dbus_pub_t *pub, u8 *buf, int len);
extern int dbus_recv_ctl(const dbus_pub_t *pub, u8 *buf, int len);
extern int dbus_get_stats(const dbus_pub_t *pub, dbus_stats_t *stats);
extern int dbus_get_attrib(const dbus_pub_t *pub, dbus_attrib_t *attrib);
extern int dbus_get_device_speed(const dbus_pub_t *pub);
extern int dbus_set_config(const dbus_pub_t *pub, dbus_config_t *config);
extern int dbus_get_config(const dbus_pub_t *pub, dbus_config_t *config);
extern void *dbus_pktget(const dbus_pub_t *pub, int len);
extern void dbus_pktfree(const dbus_pub_t *pub, void *pkt);
extern int dbus_set_errmask(const dbus_pub_t *pub, u32 mask);
extern int dbus_pnp_sleep(const dbus_pub_t *pub);
extern int dbus_pnp_resume(const dbus_pub_t *pub, int *fw_reload);
extern int dbus_pnp_disconnect(const dbus_pub_t *pub);
extern int dbus_iovar_op(const dbus_pub_t *pub, const char *name,
void *params, int plen, void *arg, int len, bool set);
#ifdef BCMDBG
extern void dbus_hist_dump(const dbus_pub_t *pub, struct bcmstrbuf *b);
#endif /* BCMDBG */
/*
* Private Common Bus Interface
*/
/* IO Request Block (IRB) */
typedef struct dbus_irb {
struct dbus_irb *next; /* it's casted from dbus_irb_tx or dbus_irb_rx struct */
} dbus_irb_t;
typedef struct dbus_irb_rx {
struct dbus_irb irb; /* Must be first */
u8 *buf;
int buf_len;
int actual_len;
void *pkt;
void *info;
void *arg;
} dbus_irb_rx_t;
typedef struct dbus_irb_tx {
struct dbus_irb irb; /* Must be first */
u8 *buf;
int len;
void *pkt;
int retry_count;
void *info;
void *arg;
} dbus_irb_tx_t;
/* DBUS interface callbacks are different from user callbacks
* so, internally, different info can be passed to upper layer
*/
typedef struct dbus_intf_callbacks {
void (*send_irb_timeout) (void *cbarg, dbus_irb_tx_t *txirb);
void (*send_irb_complete) (void *cbarg, dbus_irb_tx_t *txirb,
int status);
void (*recv_irb_complete) (void *cbarg, dbus_irb_rx_t *rxirb,
int status);
void (*errhandler) (void *cbarg, int err);
void (*ctl_complete) (void *cbarg, int type, int status);
void (*state_change) (void *cbarg, int state);
bool(*isr) (void *cbarg, bool *wantdpc);
bool(*dpc) (void *cbarg, bool bounded);
void (*watchdog) (void *cbarg);
void *(*pktget) (void *cbarg, uint len, bool send);
void (*pktfree) (void *cbarg, void *p, bool send);
struct dbus_irb *(*getirb) (void *cbarg, bool send);
void (*rxerr_indicate) (void *cbarg, bool on);
} dbus_intf_callbacks_t;
/*
* Porting: To support new bus, port these functions below
*/
/*
* Bus specific Interface
* Implemented by dbus_usb.c/dbus_sdio.c
*/
extern int dbus_bus_register(int vid, int pid, probe_cb_t prcb,
disconnect_cb_t discb, void *prarg,
dbus_intf_t **intf, void *param1, void *param2);
extern int dbus_bus_deregister(void);
/*
* Bus-specific and OS-specific Interface
* Implemented by dbus_usb_[linux/ndis].c/dbus_sdio_[linux/ndis].c
*/
extern int dbus_bus_osl_register(int vid, int pid, probe_cb_t prcb,
disconnect_cb_t discb, void *prarg,
dbus_intf_t **intf, void *param1,
void *param2);
extern int dbus_bus_osl_deregister(void);
/*
* Bus-specific, OS-specific, HW-specific Interface
* Mainly for SDIO Host HW controller
*/
extern int dbus_bus_osl_hw_register(int vid, int pid, probe_cb_t prcb,
disconnect_cb_t discb, void *prarg,
dbus_intf_t **intf);
extern int dbus_bus_osl_hw_deregister(void);
#endif /* __DBUS_H__ */