1*4882a593Smuzhiyun /* 2*4882a593Smuzhiyun * Dongle BUS interface Abstraction layer 3*4882a593Smuzhiyun * target serial buses like USB, SDIO, SPI, etc. 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * Copyright (C) 2020, Broadcom. 6*4882a593Smuzhiyun * 7*4882a593Smuzhiyun * Unless you and Broadcom execute a separate written software license 8*4882a593Smuzhiyun * agreement governing use of this software, this software is licensed to you 9*4882a593Smuzhiyun * under the terms of the GNU General Public License version 2 (the "GPL"), 10*4882a593Smuzhiyun * available at http://www.broadcom.com/licenses/GPLv2.php, with the 11*4882a593Smuzhiyun * following added to such license: 12*4882a593Smuzhiyun * 13*4882a593Smuzhiyun * As a special exception, the copyright holders of this software give you 14*4882a593Smuzhiyun * permission to link this software with independent modules, and to copy and 15*4882a593Smuzhiyun * distribute the resulting executable under terms of your choice, provided that 16*4882a593Smuzhiyun * you also meet, for each linked independent module, the terms and conditions of 17*4882a593Smuzhiyun * the license of that module. An independent module is a module which is not 18*4882a593Smuzhiyun * derived from this software. The special exception does not apply to any 19*4882a593Smuzhiyun * modifications of the software. 20*4882a593Smuzhiyun * 21*4882a593Smuzhiyun * 22*4882a593Smuzhiyun * <<Broadcom-WL-IPTag/Open:>> 23*4882a593Smuzhiyun */ 24*4882a593Smuzhiyun 25*4882a593Smuzhiyun #ifndef __DBUS_H__ 26*4882a593Smuzhiyun #define __DBUS_H__ 27*4882a593Smuzhiyun 28*4882a593Smuzhiyun #include "typedefs.h" 29*4882a593Smuzhiyun #include <dhd_linux.h> 30*4882a593Smuzhiyun 31*4882a593Smuzhiyun extern uint dbus_msglevel; 32*4882a593Smuzhiyun #define DBUS_ERROR_VAL 0x0001 33*4882a593Smuzhiyun #define DBUS_TRACE_VAL 0x0002 34*4882a593Smuzhiyun #define DBUS_INFO_VAL 0x0004 35*4882a593Smuzhiyun 36*4882a593Smuzhiyun #if defined(DHD_DEBUG) 37*4882a593Smuzhiyun #define DBUSERR(args) do {if (dbus_msglevel & DBUS_ERROR_VAL) printf args;} while (0) 38*4882a593Smuzhiyun #define DBUSTRACE(args) do {if (dbus_msglevel & DBUS_TRACE_VAL) printf args;} while (0) 39*4882a593Smuzhiyun #define DBUSINFO(args) do {if (dbus_msglevel & DBUS_INFO_VAL) printf args;} while (0) 40*4882a593Smuzhiyun #else /* defined(DHD_DEBUG) */ 41*4882a593Smuzhiyun #define DBUSERR(args) 42*4882a593Smuzhiyun #define DBUSTRACE(args) 43*4882a593Smuzhiyun #define DBUSINFO(args) 44*4882a593Smuzhiyun #endif 45*4882a593Smuzhiyun 46*4882a593Smuzhiyun enum { 47*4882a593Smuzhiyun DBUS_OK = 0, 48*4882a593Smuzhiyun DBUS_ERR = -200, 49*4882a593Smuzhiyun DBUS_ERR_TIMEOUT, 50*4882a593Smuzhiyun DBUS_ERR_DISCONNECT, 51*4882a593Smuzhiyun DBUS_ERR_NODEVICE, 52*4882a593Smuzhiyun DBUS_ERR_UNSUPPORTED, 53*4882a593Smuzhiyun DBUS_ERR_PENDING, 54*4882a593Smuzhiyun DBUS_ERR_NOMEM, 55*4882a593Smuzhiyun DBUS_ERR_TXFAIL, 56*4882a593Smuzhiyun DBUS_ERR_TXTIMEOUT, 57*4882a593Smuzhiyun DBUS_ERR_TXDROP, 58*4882a593Smuzhiyun DBUS_ERR_RXFAIL, 59*4882a593Smuzhiyun DBUS_ERR_RXDROP, 60*4882a593Smuzhiyun DBUS_ERR_TXCTLFAIL, 61*4882a593Smuzhiyun DBUS_ERR_RXCTLFAIL, 62*4882a593Smuzhiyun DBUS_ERR_REG_PARAM, 63*4882a593Smuzhiyun DBUS_STATUS_CANCELLED, 64*4882a593Smuzhiyun DBUS_ERR_NVRAM, 65*4882a593Smuzhiyun DBUS_JUMBO_NOMATCH, 66*4882a593Smuzhiyun DBUS_JUMBO_BAD_FORMAT, 67*4882a593Smuzhiyun DBUS_NVRAM_NONTXT, 68*4882a593Smuzhiyun DBUS_ERR_RXZLP 69*4882a593Smuzhiyun }; 70*4882a593Smuzhiyun 71*4882a593Smuzhiyun #define BCM_OTP_SIZE_43236 84 /* number of 16 bit values */ 72*4882a593Smuzhiyun #define BCM_OTP_SW_RGN_43236 24 /* start offset of SW config region */ 73*4882a593Smuzhiyun #define BCM_OTP_ADDR_43236 0x18000800 /* address of otp base */ 74*4882a593Smuzhiyun 75*4882a593Smuzhiyun #define ERR_CBMASK_TXFAIL 0x00000001 76*4882a593Smuzhiyun #define ERR_CBMASK_RXFAIL 0x00000002 77*4882a593Smuzhiyun #define ERR_CBMASK_ALL 0xFFFFFFFF 78*4882a593Smuzhiyun 79*4882a593Smuzhiyun #define DBUS_CBCTL_WRITE 0 80*4882a593Smuzhiyun #define DBUS_CBCTL_READ 1 81*4882a593Smuzhiyun #if defined(INTR_EP_ENABLE) 82*4882a593Smuzhiyun #define DBUS_CBINTR_POLL 2 83*4882a593Smuzhiyun #endif /* defined(INTR_EP_ENABLE) */ 84*4882a593Smuzhiyun 85*4882a593Smuzhiyun #define DBUS_TX_RETRY_LIMIT 3 /* retries for failed txirb */ 86*4882a593Smuzhiyun #define DBUS_TX_TIMEOUT_INTERVAL 250 /* timeout for txirb complete, in ms */ 87*4882a593Smuzhiyun 88*4882a593Smuzhiyun /* 89*4882a593Smuzhiyun * The max TCB/RCB data buffer size 90*4882a593Smuzhiyun * With USB RPC aggregation on, 91*4882a593Smuzhiyun * rx buffer has to be a single big chunk memory due to dongle->host aggregation 92*4882a593Smuzhiyun * Upper layer has to do byte copy to deaggregate the buffer to satisfy WL driver 93*4882a593Smuzhiyun * one buffer per pkt requirement 94*4882a593Smuzhiyun * Windows Vista may be able to use MDL to workaround this requirement 95*4882a593Smuzhiyun * tx buffer has to copy over RPC buffer since they are managed in different domain 96*4882a593Smuzhiyun * Without copy, DBUS and RPC has to break the encapsulation, which is not implemented 97*4882a593Smuzhiyun * RPC aggregated buffer arrives as a chained buffers. bypte copy needs to traverse the chain 98*4882a593Smuzhiyun * to form one continuous USB irb. 99*4882a593Smuzhiyun * These buffer size must accomodate the MAX rpc agg size in both direction 100*4882a593Smuzhiyun * #define BCM_RPC_TP_DNGL_AGG_MAX_BYTE 101*4882a593Smuzhiyun * #define BCM_RPC_TP_HOST_AGG_MAX_BYTE 102*4882a593Smuzhiyun * Without USB RPC aggregation, these buffer size can be smaller like normal 2K 103*4882a593Smuzhiyun * to fit max tcp pkt(ETH_MAX_DATA_SIZE) + d11/phy/rpc/overhead 104*4882a593Smuzhiyun * 105*4882a593Smuzhiyun * The number of buffer needed is upper layer dependent. e.g. rpc defines BCM_RPC_TP_DBUS_NTXQ 106*4882a593Smuzhiyun */ 107*4882a593Smuzhiyun #define DBUS_BUFFER_SIZE_TX 32000 108*4882a593Smuzhiyun #define DBUS_BUFFER_SIZE_RX 24000 109*4882a593Smuzhiyun 110*4882a593Smuzhiyun #define DBUS_BUFFER_SIZE_TX_NOAGG 2048 111*4882a593Smuzhiyun #define DBUS_BUFFER_SIZE_RX_NOAGG 2048 112*4882a593Smuzhiyun 113*4882a593Smuzhiyun /** DBUS types */ 114*4882a593Smuzhiyun enum { 115*4882a593Smuzhiyun DBUS_USB, 116*4882a593Smuzhiyun DBUS_SDIO, 117*4882a593Smuzhiyun DBUS_SPI, 118*4882a593Smuzhiyun DBUS_UNKNOWN 119*4882a593Smuzhiyun }; 120*4882a593Smuzhiyun 121*4882a593Smuzhiyun enum dbus_state { 122*4882a593Smuzhiyun DBUS_STATE_DL_PENDING, 123*4882a593Smuzhiyun DBUS_STATE_DL_DONE, 124*4882a593Smuzhiyun DBUS_STATE_UP, 125*4882a593Smuzhiyun DBUS_STATE_DOWN, 126*4882a593Smuzhiyun DBUS_STATE_PNP_FWDL, 127*4882a593Smuzhiyun DBUS_STATE_DISCONNECT, 128*4882a593Smuzhiyun DBUS_STATE_SLEEP, 129*4882a593Smuzhiyun DBUS_STATE_DL_NEEDED 130*4882a593Smuzhiyun }; 131*4882a593Smuzhiyun 132*4882a593Smuzhiyun enum dbus_pnp_state { 133*4882a593Smuzhiyun DBUS_PNP_DISCONNECT, 134*4882a593Smuzhiyun DBUS_PNP_SLEEP, 135*4882a593Smuzhiyun DBUS_PNP_RESUME 136*4882a593Smuzhiyun }; 137*4882a593Smuzhiyun 138*4882a593Smuzhiyun enum dbus_file { 139*4882a593Smuzhiyun DBUS_FIRMWARE, 140*4882a593Smuzhiyun DBUS_NVFILE 141*4882a593Smuzhiyun }; 142*4882a593Smuzhiyun 143*4882a593Smuzhiyun typedef enum _DEVICE_SPEED { 144*4882a593Smuzhiyun INVALID_SPEED = -1, 145*4882a593Smuzhiyun LOW_SPEED = 1, /**< USB 1.1: 1.5 Mbps */ 146*4882a593Smuzhiyun FULL_SPEED, /**< USB 1.1: 12 Mbps */ 147*4882a593Smuzhiyun HIGH_SPEED, /**< USB 2.0: 480 Mbps */ 148*4882a593Smuzhiyun SUPER_SPEED, /**< USB 3.0: 4.8 Gbps */ 149*4882a593Smuzhiyun } DEVICE_SPEED; 150*4882a593Smuzhiyun 151*4882a593Smuzhiyun typedef struct { 152*4882a593Smuzhiyun int bustype; 153*4882a593Smuzhiyun int vid; 154*4882a593Smuzhiyun int pid; 155*4882a593Smuzhiyun int devid; 156*4882a593Smuzhiyun int chiprev; /**< chip revsion number */ 157*4882a593Smuzhiyun int mtu; 158*4882a593Smuzhiyun int nchan; /**< Data Channels */ 159*4882a593Smuzhiyun int has_2nd_bulk_in_ep; 160*4882a593Smuzhiyun } dbus_attrib_t; 161*4882a593Smuzhiyun 162*4882a593Smuzhiyun /* FIX: Account for errors related to DBUS; 163*4882a593Smuzhiyun * Let upper layer account for packets/bytes 164*4882a593Smuzhiyun */ 165*4882a593Smuzhiyun typedef struct { 166*4882a593Smuzhiyun uint32 rx_errors; 167*4882a593Smuzhiyun uint32 tx_errors; 168*4882a593Smuzhiyun uint32 rx_dropped; 169*4882a593Smuzhiyun uint32 tx_dropped; 170*4882a593Smuzhiyun } dbus_stats_t; 171*4882a593Smuzhiyun 172*4882a593Smuzhiyun /** 173*4882a593Smuzhiyun * Configurable BUS parameters 174*4882a593Smuzhiyun */ 175*4882a593Smuzhiyun enum { 176*4882a593Smuzhiyun DBUS_CONFIG_ID_RXCTL_DEFERRES = 1, 177*4882a593Smuzhiyun DBUS_CONFIG_ID_AGGR_LIMIT, 178*4882a593Smuzhiyun DBUS_CONFIG_ID_KEEPIF_ON_DEVRESET 179*4882a593Smuzhiyun }; 180*4882a593Smuzhiyun 181*4882a593Smuzhiyun typedef struct { 182*4882a593Smuzhiyun uint32 config_id; 183*4882a593Smuzhiyun union { 184*4882a593Smuzhiyun uint32 general_param; 185*4882a593Smuzhiyun bool rxctl_deferrespok; 186*4882a593Smuzhiyun struct { 187*4882a593Smuzhiyun int maxrxsf; 188*4882a593Smuzhiyun int maxrxsize; 189*4882a593Smuzhiyun int maxtxsf; 190*4882a593Smuzhiyun int maxtxsize; 191*4882a593Smuzhiyun } aggr_param; 192*4882a593Smuzhiyun }; 193*4882a593Smuzhiyun } dbus_config_t; 194*4882a593Smuzhiyun 195*4882a593Smuzhiyun /** 196*4882a593Smuzhiyun * External Download Info 197*4882a593Smuzhiyun */ 198*4882a593Smuzhiyun typedef struct dbus_extdl { 199*4882a593Smuzhiyun uint8 *fw; 200*4882a593Smuzhiyun int fwlen; 201*4882a593Smuzhiyun uint8 *vars; 202*4882a593Smuzhiyun int varslen; 203*4882a593Smuzhiyun } dbus_extdl_t; 204*4882a593Smuzhiyun 205*4882a593Smuzhiyun struct dbus_callbacks; 206*4882a593Smuzhiyun struct exec_parms; 207*4882a593Smuzhiyun 208*4882a593Smuzhiyun typedef void *(*probe_cb_t)(void *arg, const char *desc, uint32 bustype, 209*4882a593Smuzhiyun uint16 bus_no, uint16 slot, uint32 hdrlen); 210*4882a593Smuzhiyun typedef void (*disconnect_cb_t)(void *arg); 211*4882a593Smuzhiyun typedef void *(*exec_cb_t)(struct exec_parms *args); 212*4882a593Smuzhiyun 213*4882a593Smuzhiyun /** Client callbacks registered during dbus_attach() */ 214*4882a593Smuzhiyun typedef struct dbus_callbacks { 215*4882a593Smuzhiyun void (*send_complete)(void *cbarg, void *info, int status); 216*4882a593Smuzhiyun void (*recv_buf)(void *cbarg, uint8 *buf, int len); 217*4882a593Smuzhiyun void (*recv_pkt)(void *cbarg, void *pkt); 218*4882a593Smuzhiyun void (*txflowcontrol)(void *cbarg, bool onoff); 219*4882a593Smuzhiyun void (*errhandler)(void *cbarg, int err); 220*4882a593Smuzhiyun void (*ctl_complete)(void *cbarg, int type, int status); 221*4882a593Smuzhiyun void (*state_change)(void *cbarg, int state); 222*4882a593Smuzhiyun void *(*pktget)(void *cbarg, uint len, bool send); 223*4882a593Smuzhiyun void (*pktfree)(void *cbarg, void *p, bool send); 224*4882a593Smuzhiyun } dbus_callbacks_t; 225*4882a593Smuzhiyun 226*4882a593Smuzhiyun struct dbus_pub; 227*4882a593Smuzhiyun struct bcmstrbuf; 228*4882a593Smuzhiyun struct dbus_irb; 229*4882a593Smuzhiyun struct dbus_irb_rx; 230*4882a593Smuzhiyun struct dbus_irb_tx; 231*4882a593Smuzhiyun struct dbus_intf_callbacks; 232*4882a593Smuzhiyun 233*4882a593Smuzhiyun typedef struct { 234*4882a593Smuzhiyun void* (*attach)(struct dbus_pub *pub, void *cbarg, struct dbus_intf_callbacks *cbs); 235*4882a593Smuzhiyun void (*detach)(struct dbus_pub *pub, void *bus); 236*4882a593Smuzhiyun 237*4882a593Smuzhiyun int (*up)(void *bus); 238*4882a593Smuzhiyun int (*down)(void *bus); 239*4882a593Smuzhiyun int (*send_irb)(void *bus, struct dbus_irb_tx *txirb); 240*4882a593Smuzhiyun int (*recv_irb)(void *bus, struct dbus_irb_rx *rxirb); 241*4882a593Smuzhiyun int (*cancel_irb)(void *bus, struct dbus_irb_tx *txirb); 242*4882a593Smuzhiyun int (*send_ctl)(void *bus, uint8 *buf, int len); 243*4882a593Smuzhiyun int (*recv_ctl)(void *bus, uint8 *buf, int len); 244*4882a593Smuzhiyun int (*get_stats)(void *bus, dbus_stats_t *stats); 245*4882a593Smuzhiyun int (*get_attrib)(void *bus, dbus_attrib_t *attrib); 246*4882a593Smuzhiyun 247*4882a593Smuzhiyun int (*pnp)(void *bus, int evnt); 248*4882a593Smuzhiyun int (*remove)(void *bus); 249*4882a593Smuzhiyun int (*resume)(void *bus); 250*4882a593Smuzhiyun int (*suspend)(void *bus); 251*4882a593Smuzhiyun int (*stop)(void *bus); 252*4882a593Smuzhiyun int (*reset)(void *bus); 253*4882a593Smuzhiyun 254*4882a593Smuzhiyun /* Access to bus buffers directly */ 255*4882a593Smuzhiyun void *(*pktget)(void *bus, int len); 256*4882a593Smuzhiyun void (*pktfree)(void *bus, void *pkt); 257*4882a593Smuzhiyun 258*4882a593Smuzhiyun int (*iovar_op)(void *bus, const char *name, void *params, int plen, void *arg, int len, 259*4882a593Smuzhiyun bool set); 260*4882a593Smuzhiyun void (*dump)(void *bus, struct bcmstrbuf *strbuf); 261*4882a593Smuzhiyun int (*set_config)(void *bus, dbus_config_t *config); 262*4882a593Smuzhiyun int (*get_config)(void *bus, dbus_config_t *config); 263*4882a593Smuzhiyun 264*4882a593Smuzhiyun bool (*device_exists)(void *bus); 265*4882a593Smuzhiyun int (*dlneeded)(void *bus); 266*4882a593Smuzhiyun int (*dlstart)(void *bus, uint8 *fw, int len); 267*4882a593Smuzhiyun int (*dlrun)(void *bus); 268*4882a593Smuzhiyun bool (*recv_needed)(void *bus); 269*4882a593Smuzhiyun 270*4882a593Smuzhiyun void *(*exec_rxlock)(void *bus, exec_cb_t func, struct exec_parms *args); 271*4882a593Smuzhiyun void *(*exec_txlock)(void *bus, exec_cb_t func, struct exec_parms *args); 272*4882a593Smuzhiyun 273*4882a593Smuzhiyun int (*tx_timer_init)(void *bus); 274*4882a593Smuzhiyun int (*tx_timer_start)(void *bus, uint timeout); 275*4882a593Smuzhiyun int (*tx_timer_stop)(void *bus); 276*4882a593Smuzhiyun 277*4882a593Smuzhiyun int (*sched_dpc)(void *bus); 278*4882a593Smuzhiyun int (*lock)(void *bus); 279*4882a593Smuzhiyun int (*unlock)(void *bus); 280*4882a593Smuzhiyun int (*sched_probe_cb)(void *bus); 281*4882a593Smuzhiyun 282*4882a593Smuzhiyun int (*shutdown)(void *bus); 283*4882a593Smuzhiyun 284*4882a593Smuzhiyun int (*recv_stop)(void *bus); 285*4882a593Smuzhiyun int (*recv_resume)(void *bus); 286*4882a593Smuzhiyun 287*4882a593Smuzhiyun int (*recv_irb_from_ep)(void *bus, struct dbus_irb_rx *rxirb, uint ep_idx); 288*4882a593Smuzhiyun 289*4882a593Smuzhiyun int (*readreg)(void *bus, uint32 regaddr, int datalen, uint32 *value); 290*4882a593Smuzhiyun 291*4882a593Smuzhiyun /* Add from the bottom */ 292*4882a593Smuzhiyun } dbus_intf_t; 293*4882a593Smuzhiyun 294*4882a593Smuzhiyun typedef struct dbus_pub { 295*4882a593Smuzhiyun struct osl_info *osh; 296*4882a593Smuzhiyun dbus_stats_t stats; 297*4882a593Smuzhiyun dbus_attrib_t attrib; 298*4882a593Smuzhiyun enum dbus_state busstate; 299*4882a593Smuzhiyun DEVICE_SPEED device_speed; 300*4882a593Smuzhiyun int ntxq, nrxq, rxsize; 301*4882a593Smuzhiyun void *bus; 302*4882a593Smuzhiyun struct shared_info *sh; 303*4882a593Smuzhiyun void *dev_info; 304*4882a593Smuzhiyun } dbus_pub_t; 305*4882a593Smuzhiyun 306*4882a593Smuzhiyun #define BUS_INFO(bus, type) (((type *) bus)->pub->bus) 307*4882a593Smuzhiyun 308*4882a593Smuzhiyun #define ALIGNED_LOCAL_VARIABLE(var, align) \ 309*4882a593Smuzhiyun uint8 buffer[SDALIGN+64]; \ 310*4882a593Smuzhiyun uint8 *var = (uint8 *)(((uintptr)&buffer[0]) & ~(align-1)) + align; 311*4882a593Smuzhiyun 312*4882a593Smuzhiyun /* 313*4882a593Smuzhiyun * Public Bus Function Interface 314*4882a593Smuzhiyun */ 315*4882a593Smuzhiyun 316*4882a593Smuzhiyun /* 317*4882a593Smuzhiyun * FIX: Is there better way to pass OS/Host handles to DBUS but still 318*4882a593Smuzhiyun * maintain common interface for all OS?? 319*4882a593Smuzhiyun * Under NDIS, param1 needs to be MiniportHandle 320*4882a593Smuzhiyun * For NDIS60, param2 is WdfDevice 321*4882a593Smuzhiyun * Under Linux, param1 and param2 are NULL; 322*4882a593Smuzhiyun */ 323*4882a593Smuzhiyun //extern int dbus_register(int vid, int pid, probe_cb_t prcb, disconnect_cb_t discb, void *prarg, 324*4882a593Smuzhiyun // void *param1, void *param2); 325*4882a593Smuzhiyun //extern int dbus_deregister(void); 326*4882a593Smuzhiyun 327*4882a593Smuzhiyun //extern int dbus_download_firmware(dbus_pub_t *pub); 328*4882a593Smuzhiyun //extern int dbus_up(struct dhd_bus *pub); 329*4882a593Smuzhiyun extern int dbus_down(dbus_pub_t *pub); 330*4882a593Smuzhiyun //extern int dbus_stop(struct dhd_bus *pub); 331*4882a593Smuzhiyun extern int dbus_shutdown(dbus_pub_t *pub); 332*4882a593Smuzhiyun extern void dbus_flowctrl_rx(dbus_pub_t *pub, bool on); 333*4882a593Smuzhiyun 334*4882a593Smuzhiyun //extern int dbus_send_txdata(dbus_pub_t *dbus, void *pktbuf); 335*4882a593Smuzhiyun extern int dbus_send_buf(dbus_pub_t *pub, uint8 *buf, int len, void *info); 336*4882a593Smuzhiyun //extern int dbus_send_pkt(dbus_pub_t *pub, void *pkt, void *info); 337*4882a593Smuzhiyun //extern int dbus_send_ctl(struct dhd_bus *pub, uint8 *buf, int len); 338*4882a593Smuzhiyun //extern int dbus_recv_ctl(struct dhd_bus *pub, uint8 *buf, int len); 339*4882a593Smuzhiyun //extern int dbus_recv_bulk(dbus_pub_t *pub, uint32 ep_idx); 340*4882a593Smuzhiyun //extern int dbus_poll_intr(dbus_pub_t *pub); 341*4882a593Smuzhiyun extern int dbus_get_stats(dbus_pub_t *pub, dbus_stats_t *stats); 342*4882a593Smuzhiyun extern int dbus_get_device_speed(dbus_pub_t *pub); 343*4882a593Smuzhiyun extern int dbus_set_config(dbus_pub_t *pub, dbus_config_t *config); 344*4882a593Smuzhiyun extern int dbus_get_config(dbus_pub_t *pub, dbus_config_t *config); 345*4882a593Smuzhiyun extern void * dbus_get_devinfo(dbus_pub_t *pub); 346*4882a593Smuzhiyun 347*4882a593Smuzhiyun extern void *dbus_pktget(dbus_pub_t *pub, int len); 348*4882a593Smuzhiyun extern void dbus_pktfree(dbus_pub_t *pub, void* pkt); 349*4882a593Smuzhiyun 350*4882a593Smuzhiyun extern int dbus_set_errmask(dbus_pub_t *pub, uint32 mask); 351*4882a593Smuzhiyun extern int dbus_pnp_sleep(dbus_pub_t *pub); 352*4882a593Smuzhiyun extern int dbus_pnp_resume(dbus_pub_t *pub, int *fw_reload); 353*4882a593Smuzhiyun extern int dbus_pnp_disconnect(dbus_pub_t *pub); 354*4882a593Smuzhiyun 355*4882a593Smuzhiyun //extern int dbus_iovar_op(dbus_pub_t *pub, const char *name, 356*4882a593Smuzhiyun // void *params, int plen, void *arg, int len, bool set); 357*4882a593Smuzhiyun #ifdef BCMDBG 358*4882a593Smuzhiyun extern void dbus_hist_dump(dbus_pub_t *pub, struct bcmstrbuf *b); 359*4882a593Smuzhiyun #endif /* BCMDBG */ 360*4882a593Smuzhiyun 361*4882a593Smuzhiyun extern void *dhd_dbus_txq(const dbus_pub_t *pub); 362*4882a593Smuzhiyun extern uint dhd_dbus_hdrlen(const dbus_pub_t *pub); 363*4882a593Smuzhiyun 364*4882a593Smuzhiyun /* 365*4882a593Smuzhiyun * Private Common Bus Interface 366*4882a593Smuzhiyun */ 367*4882a593Smuzhiyun 368*4882a593Smuzhiyun /** IO Request Block (IRB) */ 369*4882a593Smuzhiyun typedef struct dbus_irb { 370*4882a593Smuzhiyun struct dbus_irb *next; /**< it's casted from dbus_irb_tx or dbus_irb_rx struct */ 371*4882a593Smuzhiyun } dbus_irb_t; 372*4882a593Smuzhiyun 373*4882a593Smuzhiyun typedef struct dbus_irb_rx { 374*4882a593Smuzhiyun struct dbus_irb irb; /* Must be first */ 375*4882a593Smuzhiyun uint8 *buf; 376*4882a593Smuzhiyun int buf_len; 377*4882a593Smuzhiyun int actual_len; 378*4882a593Smuzhiyun void *pkt; 379*4882a593Smuzhiyun void *info; 380*4882a593Smuzhiyun void *arg; 381*4882a593Smuzhiyun } dbus_irb_rx_t; 382*4882a593Smuzhiyun 383*4882a593Smuzhiyun typedef struct dbus_irb_tx { 384*4882a593Smuzhiyun struct dbus_irb irb; /** Must be first */ 385*4882a593Smuzhiyun uint8 *buf; /** mutually exclusive with struct member 'pkt' */ 386*4882a593Smuzhiyun int len; /** length of field 'buf' */ 387*4882a593Smuzhiyun void *pkt; /** mutually exclusive with struct member 'buf' */ 388*4882a593Smuzhiyun int retry_count; 389*4882a593Smuzhiyun void *info; 390*4882a593Smuzhiyun void *arg; 391*4882a593Smuzhiyun void *send_buf; /**< linear bufffer for LINUX when aggreagtion is enabled */ 392*4882a593Smuzhiyun } dbus_irb_tx_t; 393*4882a593Smuzhiyun 394*4882a593Smuzhiyun /** 395*4882a593Smuzhiyun * DBUS interface callbacks are different from user callbacks 396*4882a593Smuzhiyun * so, internally, different info can be passed to upper layer 397*4882a593Smuzhiyun */ 398*4882a593Smuzhiyun typedef struct dbus_intf_callbacks { 399*4882a593Smuzhiyun void (*send_irb_timeout)(void *cbarg, dbus_irb_tx_t *txirb); 400*4882a593Smuzhiyun void (*send_irb_complete)(void *cbarg, dbus_irb_tx_t *txirb, int status); 401*4882a593Smuzhiyun void (*recv_irb_complete)(void *cbarg, dbus_irb_rx_t *rxirb, int status); 402*4882a593Smuzhiyun void (*errhandler)(void *cbarg, int err); 403*4882a593Smuzhiyun void (*ctl_complete)(void *cbarg, int type, int status); 404*4882a593Smuzhiyun void (*state_change)(void *cbarg, int state); 405*4882a593Smuzhiyun bool (*isr)(void *cbarg, bool *wantdpc); 406*4882a593Smuzhiyun bool (*dpc)(void *cbarg, bool bounded); 407*4882a593Smuzhiyun void (*watchdog)(void *cbarg); 408*4882a593Smuzhiyun void *(*pktget)(void *cbarg, uint len, bool send); 409*4882a593Smuzhiyun void (*pktfree)(void *cbarg, void *p, bool send); 410*4882a593Smuzhiyun struct dbus_irb* (*getirb)(void *cbarg, bool send); 411*4882a593Smuzhiyun void (*rxerr_indicate)(void *cbarg, bool on); 412*4882a593Smuzhiyun } dbus_intf_callbacks_t; 413*4882a593Smuzhiyun 414*4882a593Smuzhiyun /* callback functions */ 415*4882a593Smuzhiyun typedef struct { 416*4882a593Smuzhiyun /* probe the device */ 417*4882a593Smuzhiyun void *(*probe)(uint16 bus, uint16 slot, uint32 hdrlen); 418*4882a593Smuzhiyun /* remove the device */ 419*4882a593Smuzhiyun void (*remove)(void *context); 420*4882a593Smuzhiyun /* can we suspend now */ 421*4882a593Smuzhiyun int (*suspend)(void *context); 422*4882a593Smuzhiyun /* resume from suspend */ 423*4882a593Smuzhiyun int (*resume)(void *context); 424*4882a593Smuzhiyun } dbus_driver_t; 425*4882a593Smuzhiyun 426*4882a593Smuzhiyun /* 427*4882a593Smuzhiyun * Porting: To support new bus, port these functions below 428*4882a593Smuzhiyun */ 429*4882a593Smuzhiyun 430*4882a593Smuzhiyun /* 431*4882a593Smuzhiyun * Bus specific Interface 432*4882a593Smuzhiyun * Implemented by dbus_usb.c/dbus_sdio.c 433*4882a593Smuzhiyun */ 434*4882a593Smuzhiyun extern int dbus_bus_register(dbus_driver_t *driver, dbus_intf_t **intf); 435*4882a593Smuzhiyun extern int dbus_bus_deregister(void); 436*4882a593Smuzhiyun extern void dbus_bus_fw_get(void *bus, uint8 **fw, int *fwlen, int *decomp); 437*4882a593Smuzhiyun 438*4882a593Smuzhiyun /* 439*4882a593Smuzhiyun * Bus-specific and OS-specific Interface 440*4882a593Smuzhiyun * Implemented by dbus_usb_[linux/ndis].c/dbus_sdio_[linux/ndis].c 441*4882a593Smuzhiyun */ 442*4882a593Smuzhiyun extern int dbus_bus_osl_register(dbus_driver_t *driver, dbus_intf_t **intf); 443*4882a593Smuzhiyun extern int dbus_bus_osl_deregister(void); 444*4882a593Smuzhiyun 445*4882a593Smuzhiyun /* 446*4882a593Smuzhiyun * Bus-specific, OS-specific, HW-specific Interface 447*4882a593Smuzhiyun * Mainly for SDIO Host HW controller 448*4882a593Smuzhiyun */ 449*4882a593Smuzhiyun extern int dbus_bus_osl_hw_register(int vid, int pid, probe_cb_t prcb, disconnect_cb_t discb, 450*4882a593Smuzhiyun void *prarg, dbus_intf_t **intf); 451*4882a593Smuzhiyun extern int dbus_bus_osl_hw_deregister(void); 452*4882a593Smuzhiyun 453*4882a593Smuzhiyun extern uint usbdev_bulkin_eps(void); 454*4882a593Smuzhiyun #if defined(BCM_REQUEST_FW) 455*4882a593Smuzhiyun extern void *dbus_get_fw_nvfile(int devid, int chiprev, uint8 **fw, int *fwlen, int type, 456*4882a593Smuzhiyun uint16 boardtype, uint16 boardrev, char *path); 457*4882a593Smuzhiyun extern void dbus_release_fw_nvfile(void *firmware); 458*4882a593Smuzhiyun #endif /* #if defined(BCM_REQUEST_FW) */ 459*4882a593Smuzhiyun 460*4882a593Smuzhiyun #if defined(EHCI_FASTPATH_TX) || defined(EHCI_FASTPATH_RX) 461*4882a593Smuzhiyun /* 462*4882a593Smuzhiyun * Include file for the ECHI fastpath optimized USB 463*4882a593Smuzhiyun * Practically all the lines below have equivalent in some structures in other include (or even 464*4882a593Smuzhiyun * source) files This violates all kind of structure and layering, but cutting through layers is 465*4882a593Smuzhiyun * what the optimization is about. The definitions are NOT literally borrowed from any GPLd code; 466*4882a593Smuzhiyun * the file is intended to be GPL-clean 467*4882a593Smuzhiyun * 468*4882a593Smuzhiyun * Note that while some resemblance between this code and GPLd code in Linux might exist, it is 469*4882a593Smuzhiyun * due to the common sibling. See FreeBSD: head/sys/dev/usb/controller/ehci.h for the source of 470*4882a593Smuzhiyun * inspiration :-) 471*4882a593Smuzhiyun * 472*4882a593Smuzhiyun * The code assumes little endian throughout 473*4882a593Smuzhiyun */ 474*4882a593Smuzhiyun 475*4882a593Smuzhiyun #if !defined(__linux__) 476*4882a593Smuzhiyun #error "EHCI fastpath is for Linux only." 477*4882a593Smuzhiyun #endif 478*4882a593Smuzhiyun 479*4882a593Smuzhiyun #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) 480*4882a593Smuzhiyun /* Backward compatibility */ 481*4882a593Smuzhiyun typedef unsigned int gfp_t; 482*4882a593Smuzhiyun 483*4882a593Smuzhiyun #define dma_pool pci_pool 484*4882a593Smuzhiyun #define dma_pool_create(name, dev, size, align, alloc) \ 485*4882a593Smuzhiyun pci_pool_create(name, dev, size, align, alloc, GFP_DMA | GFP_ATOMIC) 486*4882a593Smuzhiyun #define dma_pool_destroy(pool) pci_pool_destroy(pool) 487*4882a593Smuzhiyun #define dma_pool_alloc(pool, flags, handle) pci_pool_alloc(pool, flags, handle) 488*4882a593Smuzhiyun #define dma_pool_free(pool, vaddr, addr) pci_pool_free(pool, vaddr, addr) 489*4882a593Smuzhiyun 490*4882a593Smuzhiyun #define dma_map_single(dev, addr, size, dir) pci_map_single(dev, addr, size, dir) 491*4882a593Smuzhiyun #define dma_unmap_single(dev, hnd, size, dir) pci_unmap_single(dev, hnd, size, dir) 492*4882a593Smuzhiyun #define DMA_FROM_DEVICE PCI_DMA_FROMDEVICE 493*4882a593Smuzhiyun #define DMA_TO_DEVICE PCI_DMA_TODEVICE 494*4882a593Smuzhiyun #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) */ 495*4882a593Smuzhiyun 496*4882a593Smuzhiyun /* Availability of these functions varies (when present, they have two arguments) */ 497*4882a593Smuzhiyun #ifndef hc32_to_cpu 498*4882a593Smuzhiyun #define hc32_to_cpu(x) le32_to_cpu(x) 499*4882a593Smuzhiyun #define cpu_to_hc32(x) cpu_to_le32(x) 500*4882a593Smuzhiyun typedef unsigned int __hc32; 501*4882a593Smuzhiyun #else 502*4882a593Smuzhiyun #error Two-argument functions needed 503*4882a593Smuzhiyun #endif 504*4882a593Smuzhiyun 505*4882a593Smuzhiyun /* Private USB opcode base */ 506*4882a593Smuzhiyun #define EHCI_FASTPATH 0x31 507*4882a593Smuzhiyun #define EHCI_SET_EP_BYPASS EHCI_FASTPATH 508*4882a593Smuzhiyun #define EHCI_SET_BYPASS_CB (EHCI_FASTPATH + 1) 509*4882a593Smuzhiyun #define EHCI_SET_BYPASS_DEV (EHCI_FASTPATH + 2) 510*4882a593Smuzhiyun #define EHCI_DUMP_STATE (EHCI_FASTPATH + 3) 511*4882a593Smuzhiyun #define EHCI_SET_BYPASS_POOL (EHCI_FASTPATH + 4) 512*4882a593Smuzhiyun #define EHCI_CLR_EP_BYPASS (EHCI_FASTPATH + 5) 513*4882a593Smuzhiyun 514*4882a593Smuzhiyun /* 515*4882a593Smuzhiyun * EHCI QTD structure (hardware and extension) 516*4882a593Smuzhiyun * NOTE that is does not need to (and does not) match its kernel counterpart 517*4882a593Smuzhiyun */ 518*4882a593Smuzhiyun #define EHCI_QTD_NBUFFERS 5 519*4882a593Smuzhiyun #define EHCI_QTD_ALIGN 32 520*4882a593Smuzhiyun #define EHCI_BULK_PACKET_SIZE 512 521*4882a593Smuzhiyun #define EHCI_QTD_XACTERR_MAX 32 522*4882a593Smuzhiyun 523*4882a593Smuzhiyun struct ehci_qtd { 524*4882a593Smuzhiyun /* Hardware map */ 525*4882a593Smuzhiyun volatile uint32_t qtd_next; 526*4882a593Smuzhiyun volatile uint32_t qtd_altnext; 527*4882a593Smuzhiyun volatile uint32_t qtd_status; 528*4882a593Smuzhiyun #define EHCI_QTD_GET_BYTES(x) (((x)>>16) & 0x7fff) 529*4882a593Smuzhiyun #define EHCI_QTD_IOC 0x00008000 530*4882a593Smuzhiyun #define EHCI_QTD_GET_CERR(x) (((x)>>10) & 0x3) 531*4882a593Smuzhiyun #define EHCI_QTD_SET_CERR(x) ((x) << 10) 532*4882a593Smuzhiyun #define EHCI_QTD_GET_PID(x) (((x)>>8) & 0x3) 533*4882a593Smuzhiyun #define EHCI_QTD_SET_PID(x) ((x) << 8) 534*4882a593Smuzhiyun #define EHCI_QTD_ACTIVE 0x80 535*4882a593Smuzhiyun #define EHCI_QTD_HALTED 0x40 536*4882a593Smuzhiyun #define EHCI_QTD_BUFERR 0x20 537*4882a593Smuzhiyun #define EHCI_QTD_BABBLE 0x10 538*4882a593Smuzhiyun #define EHCI_QTD_XACTERR 0x08 539*4882a593Smuzhiyun #define EHCI_QTD_MISSEDMICRO 0x04 540*4882a593Smuzhiyun volatile uint32_t qtd_buffer[EHCI_QTD_NBUFFERS]; 541*4882a593Smuzhiyun volatile uint32_t qtd_buffer_hi[EHCI_QTD_NBUFFERS]; 542*4882a593Smuzhiyun 543*4882a593Smuzhiyun /* Implementation extension */ 544*4882a593Smuzhiyun dma_addr_t qtd_self; /**< own hardware address */ 545*4882a593Smuzhiyun struct ehci_qtd *obj_next; /**< software link to the next QTD */ 546*4882a593Smuzhiyun void *rpc; /**< pointer to the rpc buffer */ 547*4882a593Smuzhiyun size_t length; /**< length of the data in the buffer */ 548*4882a593Smuzhiyun void *buff; /**< pointer to the reassembly buffer */ 549*4882a593Smuzhiyun int xacterrs; /**< retry counter for qtd xact error */ 550*4882a593Smuzhiyun } __attribute__ ((aligned(EHCI_QTD_ALIGN))); 551*4882a593Smuzhiyun 552*4882a593Smuzhiyun #define EHCI_NULL __constant_cpu_to_le32(1) /* HW null pointer shall be odd */ 553*4882a593Smuzhiyun 554*4882a593Smuzhiyun #define SHORT_READ_Q(token) (EHCI_QTD_GET_BYTES(token) != 0 && EHCI_QTD_GET_PID(token) == 1) 555*4882a593Smuzhiyun 556*4882a593Smuzhiyun /** 557*4882a593Smuzhiyun * Queue Head 558*4882a593Smuzhiyun * NOTE This structure is slightly different from the one in the kernel; but needs to stay 559*4882a593Smuzhiyun * compatible. 560*4882a593Smuzhiyun */ 561*4882a593Smuzhiyun struct ehci_qh { 562*4882a593Smuzhiyun /* Hardware map */ 563*4882a593Smuzhiyun volatile uint32_t qh_link; 564*4882a593Smuzhiyun volatile uint32_t qh_endp; 565*4882a593Smuzhiyun volatile uint32_t qh_endphub; 566*4882a593Smuzhiyun volatile uint32_t qh_curqtd; 567*4882a593Smuzhiyun 568*4882a593Smuzhiyun /* QTD overlay */ 569*4882a593Smuzhiyun volatile uint32_t ow_next; 570*4882a593Smuzhiyun volatile uint32_t ow_altnext; 571*4882a593Smuzhiyun volatile uint32_t ow_status; 572*4882a593Smuzhiyun volatile uint32_t ow_buffer [EHCI_QTD_NBUFFERS]; 573*4882a593Smuzhiyun volatile uint32_t ow_buffer_hi [EHCI_QTD_NBUFFERS]; 574*4882a593Smuzhiyun 575*4882a593Smuzhiyun /* Extension (should match the kernel layout) */ 576*4882a593Smuzhiyun dma_addr_t unused0; 577*4882a593Smuzhiyun void *unused1; 578*4882a593Smuzhiyun struct list_head unused2; 579*4882a593Smuzhiyun struct ehci_qtd *dummy; 580*4882a593Smuzhiyun struct ehci_qh *unused3; 581*4882a593Smuzhiyun 582*4882a593Smuzhiyun struct ehci_hcd *unused4; 583*4882a593Smuzhiyun #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) 584*4882a593Smuzhiyun struct kref unused5; 585*4882a593Smuzhiyun unsigned unused6; 586*4882a593Smuzhiyun 587*4882a593Smuzhiyun uint8_t unused7; 588*4882a593Smuzhiyun 589*4882a593Smuzhiyun /* periodic schedule info */ 590*4882a593Smuzhiyun uint8_t unused8; 591*4882a593Smuzhiyun uint8_t unused9; 592*4882a593Smuzhiyun uint8_t unused10; 593*4882a593Smuzhiyun uint16_t unused11; 594*4882a593Smuzhiyun uint16_t unused12; 595*4882a593Smuzhiyun uint16_t unused13; 596*4882a593Smuzhiyun struct usb_device *unused14; 597*4882a593Smuzhiyun #else 598*4882a593Smuzhiyun unsigned unused5; 599*4882a593Smuzhiyun 600*4882a593Smuzhiyun u8 unused6; 601*4882a593Smuzhiyun 602*4882a593Smuzhiyun /* periodic schedule info */ 603*4882a593Smuzhiyun u8 unused7; 604*4882a593Smuzhiyun u8 unused8; 605*4882a593Smuzhiyun u8 unused9; 606*4882a593Smuzhiyun unsigned short unused10; 607*4882a593Smuzhiyun unsigned short unused11; 608*4882a593Smuzhiyun #define NO_FRAME ((unsigned short)~0) 609*4882a593Smuzhiyun #ifdef EHCI_QUIRK_FIX 610*4882a593Smuzhiyun struct usb_device *unused12; 611*4882a593Smuzhiyun #endif /* EHCI_QUIRK_FIX */ 612*4882a593Smuzhiyun #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) */ 613*4882a593Smuzhiyun struct ehci_qtd *first_qtd; 614*4882a593Smuzhiyun /* Link to the first QTD; this is an optimized equivalent of the qtd_list field */ 615*4882a593Smuzhiyun /* NOTE that ehci_qh in ehci.h shall reserve this word */ 616*4882a593Smuzhiyun } __attribute__ ((aligned(EHCI_QTD_ALIGN))); 617*4882a593Smuzhiyun 618*4882a593Smuzhiyun #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) 619*4882a593Smuzhiyun /** The corresponding structure in the kernel is used to get the QH */ 620*4882a593Smuzhiyun struct hcd_dev { /* usb_device.hcpriv points to this */ 621*4882a593Smuzhiyun struct list_head unused0; 622*4882a593Smuzhiyun struct list_head unused1; 623*4882a593Smuzhiyun 624*4882a593Smuzhiyun /* array of QH pointers */ 625*4882a593Smuzhiyun void *ep[32]; 626*4882a593Smuzhiyun }; 627*4882a593Smuzhiyun #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) */ 628*4882a593Smuzhiyun 629*4882a593Smuzhiyun int optimize_qtd_fill_with_rpc(const dbus_pub_t *pub, int epn, struct ehci_qtd *qtd, void *rpc, 630*4882a593Smuzhiyun int token, int len); 631*4882a593Smuzhiyun int optimize_qtd_fill_with_data(const dbus_pub_t *pub, int epn, struct ehci_qtd *qtd, void *data, 632*4882a593Smuzhiyun int token, int len); 633*4882a593Smuzhiyun int optimize_submit_async(struct ehci_qtd *qtd, int epn); 634*4882a593Smuzhiyun void inline optimize_ehci_qtd_init(struct ehci_qtd *qtd, dma_addr_t dma); 635*4882a593Smuzhiyun struct ehci_qtd *optimize_ehci_qtd_alloc(gfp_t flags); 636*4882a593Smuzhiyun void optimize_ehci_qtd_free(struct ehci_qtd *qtd); 637*4882a593Smuzhiyun void optimize_submit_rx_request(const dbus_pub_t *pub, int epn, struct ehci_qtd *qtd_in, void *buf); 638*4882a593Smuzhiyun #endif /* EHCI_FASTPATH_TX || EHCI_FASTPATH_RX */ 639*4882a593Smuzhiyun 640*4882a593Smuzhiyun void dbus_flowctrl_tx(void *dbi, bool on); 641*4882a593Smuzhiyun #ifdef LINUX 642*4882a593Smuzhiyun struct device * dbus_get_dev(void); 643*4882a593Smuzhiyun #endif /* LINUX */ 644*4882a593Smuzhiyun #endif /* __DBUS_H__ */ 645