Home | History | Annotate | Line # | Download | only in pci
if_bwfm_pci.c revision 1.3
      1  1.1      maya /*	$NetBSD: if_bwfm_pci.c,v 1.3 2018/09/03 16:29:32 riastradh Exp $	*/
      2  1.1      maya /*	$OpenBSD: if_bwfm_pci.c,v 1.18 2018/02/08 05:00:38 patrick Exp $	*/
      3  1.1      maya /*
      4  1.1      maya  * Copyright (c) 2010-2016 Broadcom Corporation
      5  1.1      maya  * Copyright (c) 2017 Patrick Wildt <patrick (at) blueri.se>
      6  1.1      maya  *
      7  1.1      maya  * Permission to use, copy, modify, and/or distribute this software for any
      8  1.1      maya  * purpose with or without fee is hereby granted, provided that the above
      9  1.1      maya  * copyright notice and this permission notice appear in all copies.
     10  1.1      maya  *
     11  1.1      maya  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     12  1.1      maya  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     13  1.1      maya  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     14  1.1      maya  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     15  1.1      maya  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     16  1.1      maya  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     17  1.1      maya  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     18  1.1      maya  */
     19  1.1      maya 
     20  1.1      maya #include <sys/param.h>
     21  1.1      maya #include <sys/systm.h>
     22  1.1      maya #include <sys/buf.h>
     23  1.1      maya #include <sys/kernel.h>
     24  1.1      maya #include <sys/kmem.h>
     25  1.1      maya #include <sys/device.h>
     26  1.1      maya #include <sys/pool.h>
     27  1.1      maya #include <sys/workqueue.h>
     28  1.1      maya #include <sys/socket.h>
     29  1.1      maya 
     30  1.1      maya #include <net/bpf.h>
     31  1.1      maya #include <net/if.h>
     32  1.1      maya #include <net/if_dl.h>
     33  1.1      maya #include <net/if_ether.h>
     34  1.1      maya #include <net/if_media.h>
     35  1.1      maya 
     36  1.1      maya #include <netinet/in.h>
     37  1.1      maya 
     38  1.1      maya #include <net80211/ieee80211_var.h>
     39  1.1      maya 
     40  1.1      maya #include <dev/firmload.h>
     41  1.1      maya 
     42  1.1      maya #include <dev/pci/pcireg.h>
     43  1.1      maya #include <dev/pci/pcivar.h>
     44  1.1      maya #include <dev/pci/pcidevs.h>
     45  1.1      maya 
     46  1.1      maya #include <dev/ic/bwfmvar.h>
     47  1.1      maya #include <dev/ic/bwfmreg.h>
     48  1.1      maya #include <dev/pci/if_bwfm_pci.h>
     49  1.1      maya 
     50  1.1      maya #define BWFM_DMA_D2H_SCRATCH_BUF_LEN		8
     51  1.1      maya #define BWFM_DMA_D2H_RINGUPD_BUF_LEN		1024
     52  1.1      maya #define BWFM_DMA_H2D_IOCTL_BUF_LEN		ETHER_MAX_LEN
     53  1.1      maya 
     54  1.1      maya #define BWFM_NUM_TX_MSGRINGS			2
     55  1.1      maya #define BWFM_NUM_RX_MSGRINGS			3
     56  1.1      maya 
     57  1.1      maya #define BWFM_NUM_TX_PKTIDS			2048
     58  1.1      maya #define BWFM_NUM_RX_PKTIDS			1024
     59  1.1      maya 
     60  1.1      maya #define BWFM_NUM_TX_DESCS			1
     61  1.1      maya #define BWFM_NUM_RX_DESCS			1
     62  1.1      maya 
     63  1.1      maya #ifdef BWFM_DEBUG
     64  1.1      maya #define DPRINTF(x)	do { if (bwfm_debug > 0) printf x; } while (0)
     65  1.1      maya #define DPRINTFN(n, x)	do { if (bwfm_debug >= (n)) printf x; } while (0)
     66  1.1      maya static int bwfm_debug = 2;
     67  1.1      maya #else
     68  1.1      maya #define DPRINTF(x)	do { ; } while (0)
     69  1.1      maya #define DPRINTFN(n, x)	do { ; } while (0)
     70  1.1      maya #endif
     71  1.1      maya 
     72  1.1      maya #define DEVNAME(sc)	device_xname((sc)->sc_sc.sc_dev)
     73  1.1      maya #define letoh16		htole16
     74  1.1      maya #define letoh32		htole32
     75  1.1      maya #define nitems(x)	__arraycount(x)
     76  1.1      maya 
     77  1.1      maya enum ring_status {
     78  1.1      maya 	RING_CLOSED,
     79  1.1      maya 	RING_CLOSING,
     80  1.1      maya 	RING_OPEN,
     81  1.1      maya 	RING_OPENING,
     82  1.1      maya };
     83  1.1      maya 
     84  1.1      maya struct bwfm_pci_msgring {
     85  1.1      maya 	uint32_t		 w_idx_addr;
     86  1.1      maya 	uint32_t		 r_idx_addr;
     87  1.1      maya 	uint32_t		 w_ptr;
     88  1.1      maya 	uint32_t		 r_ptr;
     89  1.1      maya 	int			 nitem;
     90  1.1      maya 	int			 itemsz;
     91  1.1      maya 	enum ring_status	 status;
     92  1.1      maya 	struct bwfm_pci_dmamem	*ring;
     93  1.1      maya 	struct mbuf		*m;
     94  1.1      maya 
     95  1.1      maya 	int			 fifo;
     96  1.1      maya 	uint8_t			 mac[ETHER_ADDR_LEN];
     97  1.1      maya };
     98  1.1      maya 
     99  1.1      maya struct bwfm_pci_buf {
    100  1.1      maya 	bus_dmamap_t	 bb_map;
    101  1.1      maya 	struct mbuf	*bb_m;
    102  1.1      maya };
    103  1.1      maya 
    104  1.1      maya struct bwfm_pci_pkts {
    105  1.1      maya 	struct bwfm_pci_buf	*pkts;
    106  1.1      maya 	uint32_t		 npkt;
    107  1.1      maya 	int			 last;
    108  1.1      maya };
    109  1.1      maya 
    110  1.1      maya struct if_rxring {
    111  1.1      maya 	u_int	rxr_total;
    112  1.1      maya 	u_int	rxr_inuse;
    113  1.1      maya };
    114  1.1      maya 
    115  1.1      maya struct bwfm_cmd_flowring_create {
    116  1.1      maya 	struct work		 wq_cookie;
    117  1.1      maya 	struct bwfm_pci_softc	*sc;
    118  1.1      maya 	struct mbuf		*m;
    119  1.1      maya 	int			 flowid;
    120  1.1      maya 	int			 prio;
    121  1.1      maya };
    122  1.1      maya 
    123  1.1      maya struct bwfm_pci_softc {
    124  1.1      maya 	struct bwfm_softc	 sc_sc;
    125  1.1      maya 	pci_chipset_tag_t	 sc_pc;
    126  1.1      maya 	pcitag_t		 sc_tag;
    127  1.1      maya 	pcireg_t		 sc_id;
    128  1.1      maya 	void			*sc_ih;
    129  1.1      maya 	pci_intr_handle_t	*sc_pihp;
    130  1.1      maya 
    131  1.1      maya 	bus_space_tag_t		 sc_reg_iot;
    132  1.1      maya 	bus_space_handle_t	 sc_reg_ioh;
    133  1.1      maya 	bus_size_t		 sc_reg_ios;
    134  1.1      maya 
    135  1.1      maya 	bus_space_tag_t		 sc_tcm_iot;
    136  1.1      maya 	bus_space_handle_t	 sc_tcm_ioh;
    137  1.1      maya 	bus_size_t		 sc_tcm_ios;
    138  1.1      maya 
    139  1.1      maya 	bus_dma_tag_t		 sc_dmat;
    140  1.1      maya 
    141  1.1      maya 	uint32_t		 sc_shared_address;
    142  1.1      maya 	uint32_t		 sc_shared_flags;
    143  1.1      maya 	uint8_t			 sc_shared_version;
    144  1.1      maya 
    145  1.1      maya 	uint8_t			 sc_dma_idx_sz;
    146  1.1      maya 	struct bwfm_pci_dmamem	*sc_dma_idx_buf;
    147  1.1      maya 	size_t			 sc_dma_idx_bufsz;
    148  1.1      maya 
    149  1.1      maya 	uint16_t		 sc_max_rxbufpost;
    150  1.1      maya 	uint32_t		 sc_rx_dataoffset;
    151  1.1      maya 	uint32_t		 sc_htod_mb_data_addr;
    152  1.1      maya 	uint32_t		 sc_dtoh_mb_data_addr;
    153  1.1      maya 	uint32_t		 sc_ring_info_addr;
    154  1.1      maya 
    155  1.1      maya 	uint32_t		 sc_console_base_addr;
    156  1.1      maya 	uint32_t		 sc_console_buf_addr;
    157  1.1      maya 	uint32_t		 sc_console_buf_size;
    158  1.1      maya 	uint32_t		 sc_console_readidx;
    159  1.1      maya 
    160  1.1      maya 	struct pool		 sc_flowring_pool;
    161  1.1      maya 	struct workqueue	*flowring_wq;
    162  1.1      maya 
    163  1.1      maya 	uint16_t		 sc_max_flowrings;
    164  1.1      maya 	uint16_t		 sc_max_submissionrings;
    165  1.1      maya 	uint16_t		 sc_max_completionrings;
    166  1.1      maya 
    167  1.1      maya 	struct bwfm_pci_msgring	 sc_ctrl_submit;
    168  1.1      maya 	struct bwfm_pci_msgring	 sc_rxpost_submit;
    169  1.1      maya 	struct bwfm_pci_msgring	 sc_ctrl_complete;
    170  1.1      maya 	struct bwfm_pci_msgring	 sc_tx_complete;
    171  1.1      maya 	struct bwfm_pci_msgring	 sc_rx_complete;
    172  1.1      maya 	struct bwfm_pci_msgring	*sc_flowrings;
    173  1.1      maya 
    174  1.1      maya 	struct bwfm_pci_dmamem	*sc_scratch_buf;
    175  1.1      maya 	struct bwfm_pci_dmamem	*sc_ringupd_buf;
    176  1.1      maya 
    177  1.1      maya 	struct bwfm_pci_dmamem	*sc_ioctl_buf;
    178  1.1      maya 	int			 sc_ioctl_reqid;
    179  1.1      maya 	uint32_t		 sc_ioctl_resp_pktid;
    180  1.1      maya 	uint32_t		 sc_ioctl_resp_ret_len;
    181  1.1      maya 	uint32_t		 sc_ioctl_resp_status;
    182  1.1      maya 	int			 sc_ioctl_poll;
    183  1.1      maya 
    184  1.1      maya 	struct if_rxring	 sc_ioctl_ring;
    185  1.1      maya 	struct if_rxring	 sc_event_ring;
    186  1.1      maya 	struct if_rxring	 sc_rxbuf_ring;
    187  1.1      maya 
    188  1.1      maya 	struct bwfm_pci_pkts	 sc_rx_pkts;
    189  1.1      maya 	struct bwfm_pci_pkts	 sc_tx_pkts;
    190  1.1      maya 	int			 sc_tx_pkts_full;
    191  1.1      maya };
    192  1.1      maya 
    193  1.1      maya struct bwfm_pci_dmamem {
    194  1.1      maya 	bus_dmamap_t		bdm_map;
    195  1.1      maya 	bus_dma_segment_t	bdm_seg;
    196  1.1      maya 	size_t			bdm_size;
    197  1.1      maya 	char *			bdm_kva;
    198  1.1      maya };
    199  1.1      maya 
    200  1.1      maya #define BWFM_PCI_DMA_MAP(_bdm)	((_bdm)->bdm_map)
    201  1.1      maya #define BWFM_PCI_DMA_LEN(_bdm)	((_bdm)->bdm_size)
    202  1.1      maya #define BWFM_PCI_DMA_DVA(_bdm)	((_bdm)->bdm_map->dm_segs[0].ds_addr)
    203  1.1      maya #define BWFM_PCI_DMA_KVA(_bdm)	((_bdm)->bdm_kva)
    204  1.1      maya 
    205  1.1      maya static u_int	 if_rxr_get(struct if_rxring *rxr, unsigned int max);
    206  1.1      maya static void	 if_rxr_put(struct if_rxring *rxr, unsigned int n);
    207  1.1      maya static void	 if_rxr_init(struct if_rxring *rxr, unsigned int lwm, unsigned int hwm);
    208  1.1      maya 
    209  1.1      maya int		 bwfm_pci_match(device_t parent, cfdata_t match, void *aux);
    210  1.1      maya void		 bwfm_pci_attachhook(device_t);
    211  1.1      maya void		 bwfm_pci_attach(device_t, device_t, void *);
    212  1.1      maya int		 bwfm_pci_detach(device_t, int);
    213  1.1      maya 
    214  1.1      maya int		 bwfm_pci_intr(void *);
    215  1.1      maya void		 bwfm_pci_intr_enable(struct bwfm_pci_softc *);
    216  1.1      maya void		 bwfm_pci_intr_disable(struct bwfm_pci_softc *);
    217  1.1      maya int		 bwfm_pci_load_microcode(struct bwfm_pci_softc *, const u_char *,
    218  1.1      maya 		    size_t);
    219  1.1      maya void		 bwfm_pci_select_core(struct bwfm_pci_softc *, int );
    220  1.1      maya 
    221  1.1      maya struct bwfm_pci_dmamem *
    222  1.1      maya 		 bwfm_pci_dmamem_alloc(struct bwfm_pci_softc *, bus_size_t,
    223  1.1      maya 		    bus_size_t);
    224  1.1      maya void		 bwfm_pci_dmamem_free(struct bwfm_pci_softc *, struct bwfm_pci_dmamem *);
    225  1.1      maya int		 bwfm_pci_pktid_avail(struct bwfm_pci_softc *,
    226  1.1      maya 		    struct bwfm_pci_pkts *);
    227  1.1      maya int		 bwfm_pci_pktid_new(struct bwfm_pci_softc *,
    228  1.2  riastrad 		    struct bwfm_pci_pkts *, struct mbuf **,
    229  1.1      maya 		    uint32_t *, paddr_t *);
    230  1.1      maya struct mbuf *	 bwfm_pci_pktid_free(struct bwfm_pci_softc *,
    231  1.1      maya 		    struct bwfm_pci_pkts *, uint32_t);
    232  1.1      maya void		 bwfm_pci_fill_rx_ioctl_ring(struct bwfm_pci_softc *,
    233  1.1      maya 		    struct if_rxring *, uint32_t);
    234  1.1      maya void		 bwfm_pci_fill_rx_buf_ring(struct bwfm_pci_softc *);
    235  1.1      maya void		 bwfm_pci_fill_rx_rings(struct bwfm_pci_softc *);
    236  1.1      maya int		 bwfm_pci_setup_ring(struct bwfm_pci_softc *, struct bwfm_pci_msgring *,
    237  1.1      maya 		    int, size_t, uint32_t, uint32_t, int, uint32_t, uint32_t *);
    238  1.1      maya int		 bwfm_pci_setup_flowring(struct bwfm_pci_softc *, struct bwfm_pci_msgring *,
    239  1.1      maya 		    int, size_t);
    240  1.1      maya 
    241  1.1      maya void		 bwfm_pci_ring_bell(struct bwfm_pci_softc *,
    242  1.1      maya 		    struct bwfm_pci_msgring *);
    243  1.1      maya void		 bwfm_pci_ring_update_rptr(struct bwfm_pci_softc *,
    244  1.1      maya 		    struct bwfm_pci_msgring *);
    245  1.1      maya void		 bwfm_pci_ring_update_wptr(struct bwfm_pci_softc *,
    246  1.1      maya 		    struct bwfm_pci_msgring *);
    247  1.1      maya void		 bwfm_pci_ring_write_rptr(struct bwfm_pci_softc *,
    248  1.1      maya 		    struct bwfm_pci_msgring *);
    249  1.1      maya void		 bwfm_pci_ring_write_wptr(struct bwfm_pci_softc *,
    250  1.1      maya 		    struct bwfm_pci_msgring *);
    251  1.1      maya void *		 bwfm_pci_ring_write_reserve(struct bwfm_pci_softc *,
    252  1.1      maya 		    struct bwfm_pci_msgring *);
    253  1.1      maya void *		 bwfm_pci_ring_write_reserve_multi(struct bwfm_pci_softc *,
    254  1.1      maya 		    struct bwfm_pci_msgring *, int, int *);
    255  1.1      maya void *		 bwfm_pci_ring_read_avail(struct bwfm_pci_softc *,
    256  1.1      maya 		    struct bwfm_pci_msgring *, int *);
    257  1.1      maya void		 bwfm_pci_ring_read_commit(struct bwfm_pci_softc *,
    258  1.1      maya 		    struct bwfm_pci_msgring *, int);
    259  1.1      maya void		 bwfm_pci_ring_write_commit(struct bwfm_pci_softc *,
    260  1.1      maya 		    struct bwfm_pci_msgring *);
    261  1.1      maya void		 bwfm_pci_ring_write_cancel(struct bwfm_pci_softc *,
    262  1.1      maya 		    struct bwfm_pci_msgring *, int);
    263  1.1      maya 
    264  1.1      maya void		 bwfm_pci_ring_rx(struct bwfm_pci_softc *,
    265  1.1      maya 		    struct bwfm_pci_msgring *);
    266  1.1      maya void		 bwfm_pci_msg_rx(struct bwfm_pci_softc *, void *);
    267  1.1      maya 
    268  1.1      maya uint32_t	 bwfm_pci_buscore_read(struct bwfm_softc *, uint32_t);
    269  1.1      maya void		 bwfm_pci_buscore_write(struct bwfm_softc *, uint32_t,
    270  1.1      maya 		    uint32_t);
    271  1.1      maya int		 bwfm_pci_buscore_prepare(struct bwfm_softc *);
    272  1.1      maya int		 bwfm_pci_buscore_reset(struct bwfm_softc *);
    273  1.1      maya void		 bwfm_pci_buscore_activate(struct bwfm_softc *, const uint32_t);
    274  1.1      maya 
    275  1.1      maya int		 bwfm_pci_flowring_lookup(struct bwfm_pci_softc *,
    276  1.1      maya 		     struct mbuf *);
    277  1.1      maya void		 bwfm_pci_flowring_create(struct bwfm_pci_softc *,
    278  1.1      maya 		     struct mbuf *);
    279  1.1      maya void		 bwfm_pci_flowring_create_cb(struct work *, void *);
    280  1.1      maya void		 bwfm_pci_flowring_delete(struct bwfm_pci_softc *, int);
    281  1.1      maya 
    282  1.1      maya void		 bwfm_pci_stop(struct bwfm_softc *);
    283  1.1      maya int		 bwfm_pci_txcheck(struct bwfm_softc *);
    284  1.2  riastrad int		 bwfm_pci_txdata(struct bwfm_softc *, struct mbuf **);
    285  1.1      maya 
    286  1.1      maya #ifdef BWFM_DEBUG
    287  1.1      maya void		 bwfm_pci_debug_console(struct bwfm_pci_softc *);
    288  1.1      maya #endif
    289  1.1      maya 
    290  1.1      maya int		 bwfm_pci_msgbuf_query_dcmd(struct bwfm_softc *, int,
    291  1.1      maya 		    int, char *, size_t *);
    292  1.1      maya int		 bwfm_pci_msgbuf_set_dcmd(struct bwfm_softc *, int,
    293  1.1      maya 		    int, char *, size_t);
    294  1.1      maya 
    295  1.1      maya struct bwfm_buscore_ops bwfm_pci_buscore_ops = {
    296  1.1      maya 	.bc_read = bwfm_pci_buscore_read,
    297  1.1      maya 	.bc_write = bwfm_pci_buscore_write,
    298  1.1      maya 	.bc_prepare = bwfm_pci_buscore_prepare,
    299  1.1      maya 	.bc_reset = bwfm_pci_buscore_reset,
    300  1.1      maya 	.bc_setup = NULL,
    301  1.1      maya 	.bc_activate = bwfm_pci_buscore_activate,
    302  1.1      maya };
    303  1.1      maya 
    304  1.1      maya struct bwfm_bus_ops bwfm_pci_bus_ops = {
    305  1.1      maya 	.bs_init = NULL,
    306  1.1      maya 	.bs_stop = bwfm_pci_stop,
    307  1.1      maya 	.bs_txcheck = bwfm_pci_txcheck,
    308  1.1      maya 	.bs_txdata = bwfm_pci_txdata,
    309  1.1      maya 	.bs_txctl = NULL,
    310  1.1      maya 	.bs_rxctl = NULL,
    311  1.1      maya };
    312  1.1      maya 
    313  1.1      maya struct bwfm_proto_ops bwfm_pci_msgbuf_ops = {
    314  1.1      maya 	.proto_query_dcmd = bwfm_pci_msgbuf_query_dcmd,
    315  1.1      maya 	.proto_set_dcmd = bwfm_pci_msgbuf_set_dcmd,
    316  1.1      maya };
    317  1.1      maya 
    318  1.1      maya 
    319  1.1      maya CFATTACH_DECL_NEW(bwfm_pci, sizeof(struct bwfm_pci_softc),
    320  1.1      maya     bwfm_pci_match, bwfm_pci_attach, bwfm_pci_detach, NULL);
    321  1.1      maya 
    322  1.1      maya static const struct bwfm_pci_matchid {
    323  1.1      maya 	pci_vendor_id_t		bwfm_vendor;
    324  1.1      maya 	pci_product_id_t	bwfm_product;
    325  1.1      maya } bwfm_pci_devices[] = {
    326  1.1      maya 	{ PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM43602 },
    327  1.1      maya 	{ PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4350 },
    328  1.1      maya };
    329  1.1      maya 
    330  1.1      maya static struct mbuf *
    331  1.1      maya MCLGETI(struct bwfm_pci_softc *sc __unused, int how,
    332  1.1      maya     struct ifnet *ifp __unused, u_int size)
    333  1.1      maya {
    334  1.1      maya 	struct mbuf *m;
    335  1.1      maya 
    336  1.1      maya 	MGETHDR(m, how, MT_DATA);
    337  1.1      maya 	if (m == NULL)
    338  1.1      maya 		return NULL;
    339  1.1      maya 
    340  1.1      maya 	MEXTMALLOC(m, size, how);
    341  1.1      maya 	if ((m->m_flags & M_EXT) == 0) {
    342  1.1      maya 		m_freem(m);
    343  1.1      maya 		return NULL;
    344  1.1      maya 	}
    345  1.1      maya 	return m;
    346  1.1      maya }
    347  1.1      maya 
    348  1.1      maya int
    349  1.1      maya bwfm_pci_match(device_t parent, cfdata_t match, void *aux)
    350  1.1      maya {
    351  1.1      maya 	struct pci_attach_args *pa = aux;
    352  1.1      maya 
    353  1.1      maya 	if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_BROADCOM)
    354  1.1      maya 		return 0;
    355  1.1      maya 
    356  1.1      maya 	for (size_t i = 0; i < __arraycount(bwfm_pci_devices); i++)
    357  1.1      maya 		if (PCI_PRODUCT(pa->pa_id) == bwfm_pci_devices[i].bwfm_product)
    358  1.1      maya 			return 1;
    359  1.1      maya 
    360  1.1      maya 	return 0;
    361  1.1      maya }
    362  1.1      maya 
    363  1.1      maya void
    364  1.1      maya bwfm_pci_attach(device_t parent, device_t self, void *aux)
    365  1.1      maya {
    366  1.1      maya 	struct bwfm_pci_softc *sc = device_private(self);
    367  1.1      maya 	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
    368  1.1      maya 	const char *intrstr;
    369  1.1      maya 	char intrbuf[PCI_INTRSTR_LEN];
    370  1.1      maya 
    371  1.1      maya 	sc->sc_sc.sc_dev = self;
    372  1.1      maya 
    373  1.1      maya 	if (pci_mapreg_map(pa, PCI_MAPREG_START + 0x00,
    374  1.1      maya 	    PCI_MAPREG_MEM_TYPE_64BIT, 0, &sc->sc_reg_iot, &sc->sc_reg_ioh,
    375  1.1      maya 	    NULL, &sc->sc_reg_ios)) {
    376  1.1      maya 		printf(": can't map bar0\n");
    377  1.1      maya 		return;
    378  1.1      maya 	}
    379  1.1      maya 
    380  1.1      maya 	if (pci_mapreg_map(pa, PCI_MAPREG_START + 0x08,
    381  1.1      maya 	    PCI_MAPREG_MEM_TYPE_64BIT, 0, &sc->sc_tcm_iot, &sc->sc_tcm_ioh,
    382  1.1      maya 	    NULL, &sc->sc_tcm_ios)) {
    383  1.1      maya 		printf(": can't map bar1\n");
    384  1.1      maya 		goto bar0;
    385  1.1      maya 	}
    386  1.1      maya 
    387  1.1      maya 	sc->sc_pc = pa->pa_pc;
    388  1.1      maya 	sc->sc_tag = pa->pa_tag;
    389  1.1      maya 	sc->sc_id = pa->pa_id;
    390  1.1      maya 
    391  1.1      maya 	if (pci_dma64_available(pa))
    392  1.1      maya 		sc->sc_dmat = pa->pa_dmat64;
    393  1.1      maya 	else
    394  1.1      maya 		sc->sc_dmat = pa->pa_dmat;
    395  1.1      maya 
    396  1.1      maya 	/* Map and establish the interrupt. */
    397  1.1      maya 	if (pci_intr_alloc(pa, &sc->sc_pihp, NULL, 0) != 0) {
    398  1.1      maya 		printf(": couldn't map interrupt\n");
    399  1.1      maya 		goto bar1;
    400  1.1      maya 	}
    401  1.1      maya 	intrstr = pci_intr_string(pa->pa_pc, sc->sc_pihp[0], intrbuf, sizeof(intrbuf));
    402  1.1      maya 
    403  1.1      maya 	sc->sc_ih = pci_intr_establish(pa->pa_pc, sc->sc_pihp[0], IPL_NET,
    404  1.1      maya 	    bwfm_pci_intr, sc);
    405  1.1      maya 	if (sc->sc_ih == NULL) {
    406  1.1      maya 		printf(": couldn't establish interrupt");
    407  1.1      maya 		if (intrstr != NULL)
    408  1.1      maya 			printf(" at %s", intrstr);
    409  1.1      maya 		printf("\n");
    410  1.1      maya 		goto bar1;
    411  1.1      maya 	}
    412  1.1      maya 	printf(": %s\n", intrstr);
    413  1.1      maya 
    414  1.1      maya 	config_mountroot(self, bwfm_pci_attachhook);
    415  1.1      maya 	return;
    416  1.1      maya 
    417  1.1      maya bar1:
    418  1.1      maya 	bus_space_unmap(sc->sc_tcm_iot, sc->sc_tcm_ioh, sc->sc_tcm_ios);
    419  1.1      maya bar0:
    420  1.1      maya 	bus_space_unmap(sc->sc_reg_iot, sc->sc_reg_ioh, sc->sc_reg_ios);
    421  1.1      maya }
    422  1.1      maya 
    423  1.1      maya void
    424  1.1      maya bwfm_pci_attachhook(device_t self)
    425  1.1      maya {
    426  1.1      maya 	struct bwfm_pci_softc *sc = device_private(self);
    427  1.1      maya 	struct bwfm_softc *bwfm = (void *)sc;
    428  1.1      maya 	struct bwfm_pci_ringinfo ringinfo;
    429  1.1      maya 	const char *name = NULL;
    430  1.1      maya 	firmware_handle_t fwh;
    431  1.1      maya 	u_char *ucode; size_t size;
    432  1.1      maya 	uint32_t d2h_w_idx_ptr, d2h_r_idx_ptr;
    433  1.1      maya 	uint32_t h2d_w_idx_ptr, h2d_r_idx_ptr;
    434  1.1      maya 	uint32_t idx_offset, reg;
    435  1.1      maya 	int i;
    436  1.1      maya 	int error;
    437  1.1      maya 
    438  1.1      maya 	sc->sc_sc.sc_buscore_ops = &bwfm_pci_buscore_ops;
    439  1.1      maya 	if (bwfm_chip_attach(&sc->sc_sc) != 0) {
    440  1.1      maya 		printf("%s: cannot attach chip\n", DEVNAME(sc));
    441  1.1      maya 		return;
    442  1.1      maya 	}
    443  1.1      maya 
    444  1.1      maya 	bwfm_pci_select_core(sc, BWFM_AGENT_CORE_PCIE2);
    445  1.1      maya 	bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
    446  1.1      maya 	    BWFM_PCI_PCIE2REG_CONFIGADDR, 0x4e0);
    447  1.1      maya 	reg = bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh,
    448  1.1      maya 	    BWFM_PCI_PCIE2REG_CONFIGDATA);
    449  1.1      maya 	bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
    450  1.1      maya 	    BWFM_PCI_PCIE2REG_CONFIGDATA, reg);
    451  1.1      maya 
    452  1.1      maya 	switch (bwfm->sc_chip.ch_chip)
    453  1.1      maya 	{
    454  1.1      maya 	case BRCM_CC_4350_CHIP_ID:
    455  1.1      maya 		if (bwfm->sc_chip.ch_chiprev > 7)
    456  1.1      maya 			name = "brcmfmac4350-pcie.bin";
    457  1.1      maya 		else
    458  1.1      maya 			name = "brcmfmac4350c2-pcie.bin";
    459  1.1      maya 		break;
    460  1.1      maya 	case BRCM_CC_43602_CHIP_ID:
    461  1.1      maya 		name = "brcmfmac43602-pcie.bin";
    462  1.1      maya 		break;
    463  1.1      maya 	default:
    464  1.1      maya 		printf("%s: unknown firmware for chip %s\n",
    465  1.1      maya 		    DEVNAME(sc), bwfm->sc_chip.ch_name);
    466  1.1      maya 		return;
    467  1.1      maya 	}
    468  1.1      maya 
    469  1.1      maya 	if (firmware_open("if_bwfm", name, &fwh) != 0) {
    470  1.1      maya 		printf("%s: failed firmware_open of file %s\n",
    471  1.1      maya 		    DEVNAME(sc), name);
    472  1.1      maya 		return;
    473  1.1      maya 	}
    474  1.1      maya 	size = firmware_get_size(fwh);
    475  1.1      maya 	ucode = firmware_malloc(size);
    476  1.1      maya 	if (ucode == NULL) {
    477  1.1      maya 		printf("%s: failed to allocate firmware memory\n",
    478  1.1      maya 		    DEVNAME(sc));
    479  1.1      maya 		firmware_close(fwh);
    480  1.1      maya 		return;
    481  1.1      maya 	}
    482  1.1      maya 	error = firmware_read(fwh, 0, ucode, size);
    483  1.1      maya 	firmware_close(fwh);
    484  1.1      maya 	if (error != 0) {
    485  1.1      maya 		printf("%s: failed to read firmware (error %d)\n",
    486  1.1      maya 		    DEVNAME(sc), error);
    487  1.1      maya 		firmware_free(ucode, size);
    488  1.1      maya 		return;
    489  1.1      maya 	}
    490  1.1      maya 
    491  1.1      maya 	/* Retrieve RAM size from firmware. */
    492  1.1      maya 	if (size >= BWFM_RAMSIZE + 8) {
    493  1.1      maya 		uint32_t *ramsize = (uint32_t *)&ucode[BWFM_RAMSIZE];
    494  1.1      maya 		if (letoh32(ramsize[0]) == BWFM_RAMSIZE_MAGIC)
    495  1.1      maya 			bwfm->sc_chip.ch_ramsize = letoh32(ramsize[1]);
    496  1.1      maya 	}
    497  1.1      maya 
    498  1.1      maya 	if (bwfm_pci_load_microcode(sc, ucode, size) != 0) {
    499  1.1      maya 		printf("%s: could not load microcode\n",
    500  1.1      maya 		    DEVNAME(sc));
    501  1.1      maya 		kmem_free(ucode, size);
    502  1.1      maya 		return;
    503  1.1      maya 	}
    504  1.1      maya 
    505  1.1      maya 	firmware_free(ucode, size);
    506  1.1      maya 
    507  1.1      maya 	sc->sc_shared_flags = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
    508  1.1      maya 	    sc->sc_shared_address + BWFM_SHARED_INFO);
    509  1.1      maya 	sc->sc_shared_version = sc->sc_shared_flags;
    510  1.1      maya 	if (sc->sc_shared_version > BWFM_SHARED_INFO_MAX_VERSION ||
    511  1.1      maya 	    sc->sc_shared_version < BWFM_SHARED_INFO_MIN_VERSION) {
    512  1.1      maya 		printf("%s: PCIe version %d unsupported\n",
    513  1.1      maya 		    DEVNAME(sc), sc->sc_shared_version);
    514  1.1      maya 		return;
    515  1.1      maya 	}
    516  1.1      maya 
    517  1.1      maya 	if (sc->sc_shared_flags & BWFM_SHARED_INFO_DMA_INDEX) {
    518  1.1      maya 		if (sc->sc_shared_flags & BWFM_SHARED_INFO_DMA_2B_IDX)
    519  1.1      maya 			sc->sc_dma_idx_sz = sizeof(uint16_t);
    520  1.1      maya 		else
    521  1.1      maya 			sc->sc_dma_idx_sz = sizeof(uint32_t);
    522  1.1      maya 	}
    523  1.1      maya 
    524  1.1      maya 	/* Maximum RX data buffers in the ring. */
    525  1.1      maya 	sc->sc_max_rxbufpost = bus_space_read_2(sc->sc_tcm_iot, sc->sc_tcm_ioh,
    526  1.1      maya 	    sc->sc_shared_address + BWFM_SHARED_MAX_RXBUFPOST);
    527  1.1      maya 	if (sc->sc_max_rxbufpost == 0)
    528  1.1      maya 		sc->sc_max_rxbufpost = BWFM_SHARED_MAX_RXBUFPOST_DEFAULT;
    529  1.1      maya 
    530  1.1      maya 	/* Alternative offset of data in a packet */
    531  1.1      maya 	sc->sc_rx_dataoffset = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
    532  1.1      maya 	    sc->sc_shared_address + BWFM_SHARED_RX_DATAOFFSET);
    533  1.1      maya 
    534  1.1      maya 	/* For Power Management */
    535  1.1      maya 	sc->sc_htod_mb_data_addr = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
    536  1.1      maya 	    sc->sc_shared_address + BWFM_SHARED_HTOD_MB_DATA_ADDR);
    537  1.1      maya 	sc->sc_dtoh_mb_data_addr = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
    538  1.1      maya 	    sc->sc_shared_address + BWFM_SHARED_DTOH_MB_DATA_ADDR);
    539  1.1      maya 
    540  1.1      maya 	/* Ring information */
    541  1.1      maya 	sc->sc_ring_info_addr = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
    542  1.1      maya 	    sc->sc_shared_address + BWFM_SHARED_RING_INFO_ADDR);
    543  1.1      maya 
    544  1.1      maya 	/* Firmware's "dmesg" */
    545  1.1      maya 	sc->sc_console_base_addr = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
    546  1.1      maya 	    sc->sc_shared_address + BWFM_SHARED_CONSOLE_ADDR);
    547  1.1      maya 	sc->sc_console_buf_addr = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
    548  1.1      maya 	    sc->sc_console_base_addr + BWFM_CONSOLE_BUFADDR);
    549  1.1      maya 	sc->sc_console_buf_size = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
    550  1.1      maya 	    sc->sc_console_base_addr + BWFM_CONSOLE_BUFSIZE);
    551  1.1      maya 
    552  1.1      maya 	/* Read ring information. */
    553  1.1      maya 	bus_space_read_region_1(sc->sc_tcm_iot, sc->sc_tcm_ioh,
    554  1.1      maya 	    sc->sc_ring_info_addr, (void *)&ringinfo, sizeof(ringinfo));
    555  1.1      maya 
    556  1.1      maya 	if (sc->sc_shared_version >= 6) {
    557  1.1      maya 		sc->sc_max_submissionrings = le16toh(ringinfo.max_submissionrings);
    558  1.1      maya 		sc->sc_max_flowrings = le16toh(ringinfo.max_flowrings);
    559  1.1      maya 		sc->sc_max_completionrings = le16toh(ringinfo.max_completionrings);
    560  1.1      maya 	} else {
    561  1.1      maya 		sc->sc_max_submissionrings = le16toh(ringinfo.max_flowrings);
    562  1.1      maya 		sc->sc_max_flowrings = sc->sc_max_submissionrings -
    563  1.1      maya 		    BWFM_NUM_TX_MSGRINGS;
    564  1.1      maya 		sc->sc_max_completionrings = BWFM_NUM_RX_MSGRINGS;
    565  1.1      maya 	}
    566  1.1      maya 
    567  1.1      maya 	if (sc->sc_dma_idx_sz == 0) {
    568  1.1      maya 		d2h_w_idx_ptr = letoh32(ringinfo.d2h_w_idx_ptr);
    569  1.1      maya 		d2h_r_idx_ptr = letoh32(ringinfo.d2h_r_idx_ptr);
    570  1.1      maya 		h2d_w_idx_ptr = letoh32(ringinfo.h2d_w_idx_ptr);
    571  1.1      maya 		h2d_r_idx_ptr = letoh32(ringinfo.h2d_r_idx_ptr);
    572  1.1      maya 		idx_offset = sizeof(uint32_t);
    573  1.1      maya 	} else {
    574  1.1      maya 		uint64_t address;
    575  1.1      maya 
    576  1.1      maya 		/* Each TX/RX Ring has a Read and Write Ptr */
    577  1.1      maya 		sc->sc_dma_idx_bufsz = (sc->sc_max_submissionrings +
    578  1.1      maya 		    sc->sc_max_completionrings) * sc->sc_dma_idx_sz * 2;
    579  1.1      maya 		sc->sc_dma_idx_buf = bwfm_pci_dmamem_alloc(sc,
    580  1.1      maya 		    sc->sc_dma_idx_bufsz, 8);
    581  1.1      maya 		if (sc->sc_dma_idx_buf == NULL) {
    582  1.1      maya 			/* XXX: Fallback to TCM? */
    583  1.1      maya 			printf("%s: cannot allocate idx buf\n",
    584  1.1      maya 			    DEVNAME(sc));
    585  1.1      maya 			return;
    586  1.1      maya 		}
    587  1.1      maya 
    588  1.1      maya 		idx_offset = sc->sc_dma_idx_sz;
    589  1.1      maya 		h2d_w_idx_ptr = 0;
    590  1.1      maya 		address = BWFM_PCI_DMA_DVA(sc->sc_dma_idx_buf);
    591  1.1      maya 		ringinfo.h2d_w_idx_hostaddr_low =
    592  1.1      maya 		    htole32(address & 0xffffffff);
    593  1.1      maya 		ringinfo.h2d_w_idx_hostaddr_high =
    594  1.1      maya 		    htole32(address >> 32);
    595  1.1      maya 
    596  1.1      maya 		h2d_r_idx_ptr = h2d_w_idx_ptr +
    597  1.1      maya 		    sc->sc_max_submissionrings * idx_offset;
    598  1.1      maya 		address += sc->sc_max_submissionrings * idx_offset;
    599  1.1      maya 		ringinfo.h2d_r_idx_hostaddr_low =
    600  1.1      maya 		    htole32(address & 0xffffffff);
    601  1.1      maya 		ringinfo.h2d_r_idx_hostaddr_high =
    602  1.1      maya 		    htole32(address >> 32);
    603  1.1      maya 
    604  1.1      maya 		d2h_w_idx_ptr = h2d_r_idx_ptr +
    605  1.1      maya 		    sc->sc_max_submissionrings * idx_offset;
    606  1.1      maya 		address += sc->sc_max_submissionrings * idx_offset;
    607  1.1      maya 		ringinfo.d2h_w_idx_hostaddr_low =
    608  1.1      maya 		    htole32(address & 0xffffffff);
    609  1.1      maya 		ringinfo.d2h_w_idx_hostaddr_high =
    610  1.1      maya 		    htole32(address >> 32);
    611  1.1      maya 
    612  1.1      maya 		d2h_r_idx_ptr = d2h_w_idx_ptr +
    613  1.1      maya 		    sc->sc_max_completionrings * idx_offset;
    614  1.1      maya 		address += sc->sc_max_completionrings * idx_offset;
    615  1.1      maya 		ringinfo.d2h_r_idx_hostaddr_low =
    616  1.1      maya 		    htole32(address & 0xffffffff);
    617  1.1      maya 		ringinfo.d2h_r_idx_hostaddr_high =
    618  1.1      maya 		    htole32(address >> 32);
    619  1.1      maya 
    620  1.1      maya 		bus_space_write_region_1(sc->sc_tcm_iot, sc->sc_tcm_ioh,
    621  1.1      maya 		    sc->sc_ring_info_addr, (void *)&ringinfo, sizeof(ringinfo));
    622  1.1      maya 	}
    623  1.1      maya 
    624  1.1      maya 	uint32_t ring_mem_ptr = letoh32(ringinfo.ringmem);
    625  1.1      maya 	/* TX ctrl ring: Send ctrl buffers, send IOCTLs */
    626  1.1      maya 	if (bwfm_pci_setup_ring(sc, &sc->sc_ctrl_submit, 64, 40,
    627  1.1      maya 	    h2d_w_idx_ptr, h2d_r_idx_ptr, 0, idx_offset,
    628  1.1      maya 	    &ring_mem_ptr))
    629  1.1      maya 		goto cleanup;
    630  1.1      maya 	/* TX rxpost ring: Send clean data mbufs for RX */
    631  1.1      maya 	if (bwfm_pci_setup_ring(sc, &sc->sc_rxpost_submit, 512, 32,
    632  1.1      maya 	    h2d_w_idx_ptr, h2d_r_idx_ptr, 1, idx_offset,
    633  1.1      maya 	    &ring_mem_ptr))
    634  1.1      maya 		goto cleanup;
    635  1.1      maya 	/* RX completion rings: recv our filled buffers back */
    636  1.1      maya 	if (bwfm_pci_setup_ring(sc, &sc->sc_ctrl_complete, 64, 24,
    637  1.1      maya 	    d2h_w_idx_ptr, d2h_r_idx_ptr, 0, idx_offset,
    638  1.1      maya 	    &ring_mem_ptr))
    639  1.1      maya 		goto cleanup;
    640  1.1      maya 	if (bwfm_pci_setup_ring(sc, &sc->sc_tx_complete, 1024, 16,
    641  1.1      maya 	    d2h_w_idx_ptr, d2h_r_idx_ptr, 1, idx_offset,
    642  1.1      maya 	    &ring_mem_ptr))
    643  1.1      maya 		goto cleanup;
    644  1.1      maya 	if (bwfm_pci_setup_ring(sc, &sc->sc_rx_complete, 512, 32,
    645  1.1      maya 	    d2h_w_idx_ptr, d2h_r_idx_ptr, 2, idx_offset,
    646  1.1      maya 	    &ring_mem_ptr))
    647  1.1      maya 		goto cleanup;
    648  1.1      maya 
    649  1.1      maya 	/* Dynamic TX rings for actual data */
    650  1.1      maya 	sc->sc_flowrings = kmem_zalloc(sc->sc_max_flowrings *
    651  1.1      maya 	    sizeof(struct bwfm_pci_msgring), KM_SLEEP);
    652  1.1      maya 	for (i = 0; i < sc->sc_max_flowrings; i++) {
    653  1.1      maya 		struct bwfm_pci_msgring *ring = &sc->sc_flowrings[i];
    654  1.1      maya 		ring->w_idx_addr = h2d_w_idx_ptr + (i + 2) * idx_offset;
    655  1.1      maya 		ring->r_idx_addr = h2d_r_idx_ptr + (i + 2) * idx_offset;
    656  1.1      maya 	}
    657  1.1      maya 
    658  1.1      maya 	pool_init(&sc->sc_flowring_pool, sizeof(struct bwfm_cmd_flowring_create),
    659  1.1      maya 	    0, 0, 0, "bwfmpl", NULL, IPL_NET);
    660  1.1      maya 
    661  1.1      maya 	/* Scratch and ring update buffers for firmware */
    662  1.1      maya 	if ((sc->sc_scratch_buf = bwfm_pci_dmamem_alloc(sc,
    663  1.1      maya 	    BWFM_DMA_D2H_SCRATCH_BUF_LEN, 8)) == NULL)
    664  1.1      maya 		goto cleanup;
    665  1.1      maya 	bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
    666  1.1      maya 	    sc->sc_shared_address + BWFM_SHARED_DMA_SCRATCH_ADDR_LOW,
    667  1.1      maya 	    BWFM_PCI_DMA_DVA(sc->sc_scratch_buf) & 0xffffffff);
    668  1.1      maya 	bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
    669  1.1      maya 	    sc->sc_shared_address + BWFM_SHARED_DMA_SCRATCH_ADDR_HIGH,
    670  1.1      maya 	    BWFM_PCI_DMA_DVA(sc->sc_scratch_buf) >> 32);
    671  1.1      maya 	bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
    672  1.1      maya 	    sc->sc_shared_address + BWFM_SHARED_DMA_SCRATCH_LEN,
    673  1.1      maya 	    BWFM_DMA_D2H_SCRATCH_BUF_LEN);
    674  1.1      maya 
    675  1.1      maya 	if ((sc->sc_ringupd_buf = bwfm_pci_dmamem_alloc(sc,
    676  1.1      maya 	    BWFM_DMA_D2H_RINGUPD_BUF_LEN, 8)) == NULL)
    677  1.1      maya 		goto cleanup;
    678  1.1      maya 	bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
    679  1.1      maya 	    sc->sc_shared_address + BWFM_SHARED_DMA_RINGUPD_ADDR_LOW,
    680  1.1      maya 	    BWFM_PCI_DMA_DVA(sc->sc_ringupd_buf) & 0xffffffff);
    681  1.1      maya 	bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
    682  1.1      maya 	    sc->sc_shared_address + BWFM_SHARED_DMA_RINGUPD_ADDR_HIGH,
    683  1.1      maya 	    BWFM_PCI_DMA_DVA(sc->sc_ringupd_buf) >> 32);
    684  1.1      maya 	bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
    685  1.1      maya 	    sc->sc_shared_address + BWFM_SHARED_DMA_RINGUPD_LEN,
    686  1.1      maya 	    BWFM_DMA_D2H_RINGUPD_BUF_LEN);
    687  1.1      maya 
    688  1.1      maya 	if ((sc->sc_ioctl_buf = bwfm_pci_dmamem_alloc(sc,
    689  1.1      maya 	    BWFM_DMA_H2D_IOCTL_BUF_LEN, 8)) == NULL)
    690  1.1      maya 		goto cleanup;
    691  1.1      maya 
    692  1.1      maya 	if (workqueue_create(&sc->flowring_wq, "bwfmflow",
    693  1.1      maya 	    bwfm_pci_flowring_create_cb, sc, PRI_SOFTNET, IPL_NET, 0))
    694  1.1      maya 		goto cleanup;
    695  1.1      maya 
    696  1.1      maya 	bwfm_pci_select_core(sc, BWFM_AGENT_CORE_PCIE2);
    697  1.1      maya 	bwfm_pci_intr_enable(sc);
    698  1.1      maya 
    699  1.1      maya 	/* Maps RX mbufs to a packet id and back. */
    700  1.1      maya 	sc->sc_rx_pkts.npkt = BWFM_NUM_RX_PKTIDS;
    701  1.1      maya 	sc->sc_rx_pkts.pkts = kmem_zalloc(BWFM_NUM_RX_PKTIDS *
    702  1.1      maya 	    sizeof(struct bwfm_pci_buf), KM_SLEEP);
    703  1.1      maya 	for (i = 0; i < BWFM_NUM_RX_PKTIDS; i++)
    704  1.1      maya 		bus_dmamap_create(sc->sc_dmat, MSGBUF_MAX_PKT_SIZE,
    705  1.1      maya 		    BWFM_NUM_RX_DESCS, MSGBUF_MAX_PKT_SIZE, 0, BUS_DMA_WAITOK,
    706  1.1      maya 		    &sc->sc_rx_pkts.pkts[i].bb_map);
    707  1.1      maya 
    708  1.1      maya 	/* Maps TX mbufs to a packet id and back. */
    709  1.1      maya 	sc->sc_tx_pkts.npkt = BWFM_NUM_TX_PKTIDS;
    710  1.1      maya 	sc->sc_tx_pkts.pkts = kmem_zalloc(BWFM_NUM_TX_PKTIDS
    711  1.1      maya 	    * sizeof(struct bwfm_pci_buf), KM_SLEEP);
    712  1.1      maya 	for (i = 0; i < BWFM_NUM_TX_PKTIDS; i++)
    713  1.1      maya 		bus_dmamap_create(sc->sc_dmat, MSGBUF_MAX_PKT_SIZE,
    714  1.1      maya 		    BWFM_NUM_TX_DESCS, MSGBUF_MAX_PKT_SIZE, 0, BUS_DMA_WAITOK,
    715  1.1      maya 		    &sc->sc_tx_pkts.pkts[i].bb_map);
    716  1.1      maya 
    717  1.1      maya 	/*
    718  1.1      maya 	 * For whatever reason, could also be a bug somewhere in this
    719  1.1      maya 	 * driver, the firmware needs a bunch of RX buffers otherwise
    720  1.1      maya 	 * it won't send any RX complete messages.  64 buffers don't
    721  1.1      maya 	 * suffice, but 128 buffers are enough.
    722  1.1      maya 	 */
    723  1.1      maya 	if_rxr_init(&sc->sc_rxbuf_ring, 128, sc->sc_max_rxbufpost);
    724  1.1      maya 	if_rxr_init(&sc->sc_ioctl_ring, 8, 8);
    725  1.1      maya 	if_rxr_init(&sc->sc_event_ring, 8, 8);
    726  1.1      maya 	bwfm_pci_fill_rx_rings(sc);
    727  1.1      maya 
    728  1.1      maya 
    729  1.1      maya #ifdef BWFM_DEBUG
    730  1.1      maya 	sc->sc_console_readidx = 0;
    731  1.1      maya 	bwfm_pci_debug_console(sc);
    732  1.1      maya #endif
    733  1.1      maya 
    734  1.1      maya 	sc->sc_ioctl_poll = 1;
    735  1.1      maya 	sc->sc_sc.sc_bus_ops = &bwfm_pci_bus_ops;
    736  1.1      maya 	sc->sc_sc.sc_proto_ops = &bwfm_pci_msgbuf_ops;
    737  1.1      maya 	bwfm_attach(&sc->sc_sc);
    738  1.1      maya 	sc->sc_ioctl_poll = 0;
    739  1.1      maya 	return;
    740  1.1      maya 
    741  1.1      maya cleanup:
    742  1.1      maya 	if (sc->flowring_wq != NULL)
    743  1.1      maya 		workqueue_destroy(sc->flowring_wq);
    744  1.1      maya 	if (sc->sc_ih != NULL) {
    745  1.1      maya 		pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
    746  1.1      maya 		pci_intr_release(sc->sc_pc, sc->sc_pihp, 1);
    747  1.1      maya 	}
    748  1.1      maya 	if (sc->sc_ioctl_buf)
    749  1.1      maya 		bwfm_pci_dmamem_free(sc, sc->sc_ioctl_buf);
    750  1.1      maya 	if (sc->sc_ringupd_buf)
    751  1.1      maya 		bwfm_pci_dmamem_free(sc, sc->sc_ringupd_buf);
    752  1.1      maya 	if (sc->sc_scratch_buf)
    753  1.1      maya 		bwfm_pci_dmamem_free(sc, sc->sc_scratch_buf);
    754  1.1      maya 	if (sc->sc_rx_complete.ring)
    755  1.1      maya 		bwfm_pci_dmamem_free(sc, sc->sc_rx_complete.ring);
    756  1.1      maya 	if (sc->sc_tx_complete.ring)
    757  1.1      maya 		bwfm_pci_dmamem_free(sc, sc->sc_tx_complete.ring);
    758  1.1      maya 	if (sc->sc_ctrl_complete.ring)
    759  1.1      maya 		bwfm_pci_dmamem_free(sc, sc->sc_ctrl_complete.ring);
    760  1.1      maya 	if (sc->sc_rxpost_submit.ring)
    761  1.1      maya 		bwfm_pci_dmamem_free(sc, sc->sc_rxpost_submit.ring);
    762  1.1      maya 	if (sc->sc_ctrl_submit.ring)
    763  1.1      maya 		bwfm_pci_dmamem_free(sc, sc->sc_ctrl_submit.ring);
    764  1.1      maya 	if (sc->sc_dma_idx_buf)
    765  1.1      maya 		bwfm_pci_dmamem_free(sc, sc->sc_dma_idx_buf);
    766  1.1      maya }
    767  1.1      maya 
    768  1.1      maya int
    769  1.1      maya bwfm_pci_load_microcode(struct bwfm_pci_softc *sc, const u_char *ucode, size_t size)
    770  1.1      maya {
    771  1.1      maya 	struct bwfm_softc *bwfm = (void *)sc;
    772  1.1      maya 	struct bwfm_core *core;
    773  1.1      maya 	uint32_t shared;
    774  1.1      maya 	int i;
    775  1.1      maya 
    776  1.1      maya 	if (bwfm->sc_chip.ch_chip == BRCM_CC_43602_CHIP_ID) {
    777  1.1      maya 		bwfm_pci_select_core(sc, BWFM_AGENT_CORE_ARM_CR4);
    778  1.1      maya 		bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
    779  1.1      maya 		    BWFM_PCI_ARMCR4REG_BANKIDX, 5);
    780  1.1      maya 		bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
    781  1.1      maya 		    BWFM_PCI_ARMCR4REG_BANKPDA, 0);
    782  1.1      maya 		bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
    783  1.1      maya 		    BWFM_PCI_ARMCR4REG_BANKIDX, 7);
    784  1.1      maya 		bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
    785  1.1      maya 		    BWFM_PCI_ARMCR4REG_BANKPDA, 0);
    786  1.1      maya 	}
    787  1.1      maya 
    788  1.1      maya 	for (i = 0; i < size; i++)
    789  1.1      maya 		bus_space_write_1(sc->sc_tcm_iot, sc->sc_tcm_ioh,
    790  1.1      maya 		    bwfm->sc_chip.ch_rambase + i, ucode[i]);
    791  1.1      maya 
    792  1.1      maya 	/* Firmware replaces this with a pointer once up. */
    793  1.1      maya 	bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
    794  1.1      maya 	    bwfm->sc_chip.ch_rambase + bwfm->sc_chip.ch_ramsize - 4, 0);
    795  1.1      maya 
    796  1.1      maya 	/* TODO: restore NVRAM */
    797  1.1      maya 
    798  1.1      maya 	/* Load reset vector from firmware and kickstart core. */
    799  1.1      maya 	if (bwfm->sc_chip.ch_chip == BRCM_CC_43602_CHIP_ID) {
    800  1.1      maya 		core = bwfm_chip_get_core(bwfm, BWFM_AGENT_INTERNAL_MEM);
    801  1.1      maya 		bwfm->sc_chip.ch_core_reset(bwfm, core, 0, 0, 0);
    802  1.1      maya 	}
    803  1.1      maya 	bwfm_chip_set_active(bwfm, *(const uint32_t *)ucode);
    804  1.1      maya 
    805  1.1      maya 	for (i = 0; i < 40; i++) {
    806  1.1      maya 		delay(50 * 1000);
    807  1.1      maya 		shared = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
    808  1.1      maya 		    bwfm->sc_chip.ch_rambase + bwfm->sc_chip.ch_ramsize - 4);
    809  1.1      maya 		if (shared)
    810  1.1      maya 			break;
    811  1.1      maya 	}
    812  1.1      maya 	if (!shared) {
    813  1.1      maya 		printf("%s: firmware did not come up\n", DEVNAME(sc));
    814  1.1      maya 		return 1;
    815  1.1      maya 	}
    816  1.1      maya 
    817  1.1      maya 	sc->sc_shared_address = shared;
    818  1.1      maya 	return 0;
    819  1.1      maya }
    820  1.1      maya 
    821  1.1      maya int
    822  1.1      maya bwfm_pci_detach(device_t self, int flags)
    823  1.1      maya {
    824  1.1      maya 	struct bwfm_pci_softc *sc = device_private(self);
    825  1.1      maya 
    826  1.1      maya 	bwfm_detach(&sc->sc_sc, flags);
    827  1.1      maya 
    828  1.1      maya 	/* FIXME: free RX buffers */
    829  1.1      maya 	/* FIXME: free TX buffers */
    830  1.1      maya 	/* FIXME: free more memory */
    831  1.1      maya 
    832  1.1      maya 	kmem_free(sc->sc_flowrings, sc->sc_max_flowrings
    833  1.1      maya 	    * sizeof(struct bwfm_pci_msgring));
    834  1.1      maya 	pool_destroy(&sc->sc_flowring_pool);
    835  1.1      maya 
    836  1.1      maya 	workqueue_destroy(sc->flowring_wq);
    837  1.1      maya 	pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
    838  1.1      maya 	pci_intr_release(sc->sc_pc, sc->sc_pihp, 1);
    839  1.1      maya 	bwfm_pci_dmamem_free(sc, sc->sc_ioctl_buf);
    840  1.1      maya 	bwfm_pci_dmamem_free(sc, sc->sc_ringupd_buf);
    841  1.1      maya 	bwfm_pci_dmamem_free(sc, sc->sc_scratch_buf);
    842  1.1      maya 	bwfm_pci_dmamem_free(sc, sc->sc_rx_complete.ring);
    843  1.1      maya 	bwfm_pci_dmamem_free(sc, sc->sc_tx_complete.ring);
    844  1.1      maya 	bwfm_pci_dmamem_free(sc, sc->sc_ctrl_complete.ring);
    845  1.1      maya 	bwfm_pci_dmamem_free(sc, sc->sc_rxpost_submit.ring);
    846  1.1      maya 	bwfm_pci_dmamem_free(sc, sc->sc_ctrl_submit.ring);
    847  1.1      maya 	bwfm_pci_dmamem_free(sc, sc->sc_dma_idx_buf);
    848  1.1      maya 	return 0;
    849  1.1      maya }
    850  1.1      maya 
    851  1.1      maya /* DMA code */
    852  1.1      maya struct bwfm_pci_dmamem *
    853  1.1      maya bwfm_pci_dmamem_alloc(struct bwfm_pci_softc *sc, bus_size_t size, bus_size_t align)
    854  1.1      maya {
    855  1.1      maya 	struct bwfm_pci_dmamem *bdm;
    856  1.1      maya 	int nsegs;
    857  1.1      maya 
    858  1.1      maya 	bdm = kmem_zalloc(sizeof(*bdm), KM_SLEEP);
    859  1.1      maya 	bdm->bdm_size = size;
    860  1.1      maya 
    861  1.1      maya 	if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
    862  1.1      maya 	    BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &bdm->bdm_map) != 0)
    863  1.1      maya 		goto bdmfree;
    864  1.1      maya 
    865  1.1      maya 	if (bus_dmamem_alloc(sc->sc_dmat, size, align, 0, &bdm->bdm_seg, 1,
    866  1.1      maya 	    &nsegs, BUS_DMA_WAITOK) != 0)
    867  1.1      maya 		goto destroy;
    868  1.1      maya 
    869  1.1      maya 	if (bus_dmamem_map(sc->sc_dmat, &bdm->bdm_seg, nsegs, size,
    870  1.1      maya 	    (void **) &bdm->bdm_kva, BUS_DMA_WAITOK | BUS_DMA_COHERENT) != 0)
    871  1.1      maya 		goto free;
    872  1.1      maya 
    873  1.1      maya 	if (bus_dmamap_load(sc->sc_dmat, bdm->bdm_map, bdm->bdm_kva, size,
    874  1.1      maya 	    NULL, BUS_DMA_WAITOK) != 0)
    875  1.1      maya 		goto unmap;
    876  1.1      maya 
    877  1.1      maya 	bzero(bdm->bdm_kva, size);
    878  1.1      maya 
    879  1.1      maya 	return (bdm);
    880  1.1      maya 
    881  1.1      maya unmap:
    882  1.1      maya 	bus_dmamem_unmap(sc->sc_dmat, bdm->bdm_kva, size);
    883  1.1      maya free:
    884  1.1      maya 	bus_dmamem_free(sc->sc_dmat, &bdm->bdm_seg, 1);
    885  1.1      maya destroy:
    886  1.1      maya 	bus_dmamap_destroy(sc->sc_dmat, bdm->bdm_map);
    887  1.1      maya bdmfree:
    888  1.1      maya 	kmem_free(bdm, sizeof(*bdm));
    889  1.1      maya 
    890  1.1      maya 	return (NULL);
    891  1.1      maya }
    892  1.1      maya 
    893  1.1      maya void
    894  1.1      maya bwfm_pci_dmamem_free(struct bwfm_pci_softc *sc, struct bwfm_pci_dmamem *bdm)
    895  1.1      maya {
    896  1.1      maya 	bus_dmamem_unmap(sc->sc_dmat, bdm->bdm_kva, bdm->bdm_size);
    897  1.1      maya 	bus_dmamem_free(sc->sc_dmat, &bdm->bdm_seg, 1);
    898  1.1      maya 	bus_dmamap_destroy(sc->sc_dmat, bdm->bdm_map);
    899  1.1      maya 	kmem_free(bdm, sizeof(*bdm));
    900  1.1      maya }
    901  1.1      maya 
    902  1.1      maya /*
    903  1.1      maya  * We need a simple mapping from a packet ID to mbufs, because when
    904  1.1      maya  * a transfer completed, we only know the ID so we have to look up
    905  1.1      maya  * the memory for the ID.  This simply looks for an empty slot.
    906  1.1      maya  */
    907  1.1      maya int
    908  1.1      maya bwfm_pci_pktid_avail(struct bwfm_pci_softc *sc, struct bwfm_pci_pkts *pkts)
    909  1.1      maya {
    910  1.1      maya 	int i, idx;
    911  1.1      maya 
    912  1.1      maya 	idx = pkts->last + 1;
    913  1.1      maya 	for (i = 0; i < pkts->npkt; i++) {
    914  1.1      maya 		if (idx == pkts->npkt)
    915  1.1      maya 			idx = 0;
    916  1.1      maya 		if (pkts->pkts[idx].bb_m == NULL)
    917  1.1      maya 			return 0;
    918  1.1      maya 		idx++;
    919  1.1      maya 	}
    920  1.1      maya 	return ENOBUFS;
    921  1.1      maya }
    922  1.1      maya 
    923  1.1      maya int
    924  1.1      maya bwfm_pci_pktid_new(struct bwfm_pci_softc *sc, struct bwfm_pci_pkts *pkts,
    925  1.2  riastrad     struct mbuf **mp, uint32_t *pktid, paddr_t *paddr)
    926  1.1      maya {
    927  1.1      maya 	int i, idx;
    928  1.1      maya 
    929  1.1      maya 	idx = pkts->last + 1;
    930  1.1      maya 	for (i = 0; i < pkts->npkt; i++) {
    931  1.1      maya 		if (idx == pkts->npkt)
    932  1.1      maya 			idx = 0;
    933  1.1      maya 		if (pkts->pkts[idx].bb_m == NULL) {
    934  1.1      maya 			if (bus_dmamap_load_mbuf(sc->sc_dmat,
    935  1.2  riastrad 			    pkts->pkts[idx].bb_map, *mp, BUS_DMA_NOWAIT) != 0) {
    936  1.2  riastrad 				/*
    937  1.2  riastrad 				 * Didn't fit.  Maybe it has too many
    938  1.2  riastrad 				 * segments.  If it has only one
    939  1.2  riastrad 				 * segment, fail; otherwise try to
    940  1.2  riastrad 				 * compact it into a single mbuf
    941  1.2  riastrad 				 * segment.
    942  1.2  riastrad 				 */
    943  1.2  riastrad 				if ((*mp)->m_next == NULL)
    944  1.2  riastrad 					return ENOBUFS;
    945  1.2  riastrad 				struct mbuf *m0 = MCLGETI(NULL, M_DONTWAIT,
    946  1.2  riastrad 				    NULL, MSGBUF_MAX_PKT_SIZE);
    947  1.2  riastrad 				if (m0 == NULL)
    948  1.2  riastrad 					return ENOBUFS;
    949  1.2  riastrad 				m_copydata(*mp, 0, (*mp)->m_pkthdr.len,
    950  1.2  riastrad 				    mtod(m0, void *));
    951  1.2  riastrad 				m0->m_pkthdr.len = m0->m_len =
    952  1.2  riastrad 				    (*mp)->m_pkthdr.len;
    953  1.2  riastrad 				m_freem(*mp);
    954  1.2  riastrad 				*mp = m0;
    955  1.1      maya 				if (bus_dmamap_load_mbuf(sc->sc_dmat,
    956  1.2  riastrad 				    pkts->pkts[idx].bb_map, *mp, BUS_DMA_NOWAIT) != 0)
    957  1.1      maya 					return EFBIG;
    958  1.1      maya 			}
    959  1.1      maya 			pkts->last = idx;
    960  1.2  riastrad 			pkts->pkts[idx].bb_m = *mp;
    961  1.1      maya 			*pktid = idx;
    962  1.1      maya 			*paddr = pkts->pkts[idx].bb_map->dm_segs[0].ds_addr;
    963  1.1      maya 			return 0;
    964  1.1      maya 		}
    965  1.1      maya 		idx++;
    966  1.1      maya 	}
    967  1.1      maya 	return ENOBUFS;
    968  1.1      maya }
    969  1.1      maya 
    970  1.1      maya struct mbuf *
    971  1.1      maya bwfm_pci_pktid_free(struct bwfm_pci_softc *sc, struct bwfm_pci_pkts *pkts,
    972  1.1      maya     uint32_t pktid)
    973  1.1      maya {
    974  1.1      maya 	struct mbuf *m;
    975  1.1      maya 
    976  1.1      maya 	if (pktid >= pkts->npkt || pkts->pkts[pktid].bb_m == NULL)
    977  1.1      maya 		return NULL;
    978  1.1      maya 	bus_dmamap_unload(sc->sc_dmat, pkts->pkts[pktid].bb_map);
    979  1.1      maya 	m = pkts->pkts[pktid].bb_m;
    980  1.1      maya 	pkts->pkts[pktid].bb_m = NULL;
    981  1.1      maya 	return m;
    982  1.1      maya }
    983  1.1      maya 
    984  1.1      maya void
    985  1.1      maya bwfm_pci_fill_rx_rings(struct bwfm_pci_softc *sc)
    986  1.1      maya {
    987  1.1      maya 	bwfm_pci_fill_rx_buf_ring(sc);
    988  1.1      maya 	bwfm_pci_fill_rx_ioctl_ring(sc, &sc->sc_ioctl_ring,
    989  1.1      maya 	    MSGBUF_TYPE_IOCTLRESP_BUF_POST);
    990  1.1      maya 	bwfm_pci_fill_rx_ioctl_ring(sc, &sc->sc_event_ring,
    991  1.1      maya 	    MSGBUF_TYPE_EVENT_BUF_POST);
    992  1.1      maya }
    993  1.1      maya 
    994  1.1      maya void
    995  1.1      maya bwfm_pci_fill_rx_ioctl_ring(struct bwfm_pci_softc *sc, struct if_rxring *rxring,
    996  1.1      maya     uint32_t msgtype)
    997  1.1      maya {
    998  1.1      maya 	struct msgbuf_rx_ioctl_resp_or_event *req;
    999  1.1      maya 	struct mbuf *m;
   1000  1.1      maya 	uint32_t pktid;
   1001  1.1      maya 	paddr_t paddr;
   1002  1.1      maya 	int s, slots;
   1003  1.1      maya 
   1004  1.1      maya 	s = splnet();
   1005  1.1      maya 	for (slots = if_rxr_get(rxring, 8); slots > 0; slots--) {
   1006  1.1      maya 		if (bwfm_pci_pktid_avail(sc, &sc->sc_rx_pkts))
   1007  1.1      maya 			break;
   1008  1.1      maya 		req = bwfm_pci_ring_write_reserve(sc, &sc->sc_ctrl_submit);
   1009  1.1      maya 		if (req == NULL)
   1010  1.1      maya 			break;
   1011  1.1      maya 		m = MCLGETI(NULL, M_DONTWAIT, NULL, MSGBUF_MAX_PKT_SIZE);
   1012  1.1      maya 		if (m == NULL) {
   1013  1.1      maya 			bwfm_pci_ring_write_cancel(sc, &sc->sc_ctrl_submit, 1);
   1014  1.1      maya 			break;
   1015  1.1      maya 		}
   1016  1.1      maya 		m->m_len = m->m_pkthdr.len = MSGBUF_MAX_PKT_SIZE;
   1017  1.2  riastrad 		if (bwfm_pci_pktid_new(sc, &sc->sc_rx_pkts, &m, &pktid, &paddr)) {
   1018  1.1      maya 			bwfm_pci_ring_write_cancel(sc, &sc->sc_ctrl_submit, 1);
   1019  1.1      maya 			m_freem(m);
   1020  1.1      maya 			break;
   1021  1.1      maya 		}
   1022  1.1      maya 		memset(req, 0, sizeof(*req));
   1023  1.1      maya 		req->msg.msgtype = msgtype;
   1024  1.1      maya 		req->msg.request_id = htole32(pktid);
   1025  1.1      maya 		req->host_buf_len = htole16(MSGBUF_MAX_PKT_SIZE);
   1026  1.1      maya 		req->host_buf_addr.high_addr = htole32(paddr >> 32);
   1027  1.1      maya 		req->host_buf_addr.low_addr = htole32(paddr & 0xffffffff);
   1028  1.1      maya 		bwfm_pci_ring_write_commit(sc, &sc->sc_ctrl_submit);
   1029  1.1      maya 	}
   1030  1.1      maya 	if_rxr_put(rxring, slots);
   1031  1.1      maya 	splx(s);
   1032  1.1      maya }
   1033  1.1      maya 
   1034  1.1      maya void
   1035  1.1      maya bwfm_pci_fill_rx_buf_ring(struct bwfm_pci_softc *sc)
   1036  1.1      maya {
   1037  1.1      maya 	struct msgbuf_rx_bufpost *req;
   1038  1.1      maya 	struct mbuf *m;
   1039  1.1      maya 	uint32_t pktid;
   1040  1.1      maya 	paddr_t paddr;
   1041  1.1      maya 	int s, slots;
   1042  1.1      maya 
   1043  1.1      maya 	s = splnet();
   1044  1.1      maya 	for (slots = if_rxr_get(&sc->sc_rxbuf_ring, sc->sc_max_rxbufpost);
   1045  1.1      maya 	    slots > 0; slots--) {
   1046  1.1      maya 		if (bwfm_pci_pktid_avail(sc, &sc->sc_rx_pkts))
   1047  1.1      maya 			break;
   1048  1.1      maya 		req = bwfm_pci_ring_write_reserve(sc, &sc->sc_rxpost_submit);
   1049  1.1      maya 		if (req == NULL)
   1050  1.1      maya 			break;
   1051  1.1      maya 		m = MCLGETI(NULL, M_DONTWAIT, NULL, MSGBUF_MAX_PKT_SIZE);
   1052  1.1      maya 		if (m == NULL) {
   1053  1.1      maya 			bwfm_pci_ring_write_cancel(sc, &sc->sc_rxpost_submit, 1);
   1054  1.1      maya 			break;
   1055  1.1      maya 		}
   1056  1.1      maya 		m->m_len = m->m_pkthdr.len = MSGBUF_MAX_PKT_SIZE;
   1057  1.2  riastrad 		if (bwfm_pci_pktid_new(sc, &sc->sc_rx_pkts, &m, &pktid, &paddr)) {
   1058  1.1      maya 			bwfm_pci_ring_write_cancel(sc, &sc->sc_rxpost_submit, 1);
   1059  1.1      maya 			m_freem(m);
   1060  1.1      maya 			break;
   1061  1.1      maya 		}
   1062  1.1      maya 		memset(req, 0, sizeof(*req));
   1063  1.1      maya 		req->msg.msgtype = MSGBUF_TYPE_RXBUF_POST;
   1064  1.1      maya 		req->msg.request_id = htole32(pktid);
   1065  1.1      maya 		req->data_buf_len = htole16(MSGBUF_MAX_PKT_SIZE);
   1066  1.1      maya 		req->data_buf_addr.high_addr = htole32(paddr >> 32);
   1067  1.1      maya 		req->data_buf_addr.low_addr = htole32(paddr & 0xffffffff);
   1068  1.1      maya 		bwfm_pci_ring_write_commit(sc, &sc->sc_rxpost_submit);
   1069  1.1      maya 	}
   1070  1.1      maya 	if_rxr_put(&sc->sc_rxbuf_ring, slots);
   1071  1.1      maya 	splx(s);
   1072  1.1      maya }
   1073  1.1      maya 
   1074  1.1      maya int
   1075  1.1      maya bwfm_pci_setup_ring(struct bwfm_pci_softc *sc, struct bwfm_pci_msgring *ring,
   1076  1.1      maya     int nitem, size_t itemsz, uint32_t w_idx, uint32_t r_idx,
   1077  1.1      maya     int idx, uint32_t idx_off, uint32_t *ring_mem)
   1078  1.1      maya {
   1079  1.1      maya 	ring->w_idx_addr = w_idx + idx * idx_off;
   1080  1.1      maya 	ring->r_idx_addr = r_idx + idx * idx_off;
   1081  1.1      maya 	ring->nitem = nitem;
   1082  1.1      maya 	ring->itemsz = itemsz;
   1083  1.1      maya 	bwfm_pci_ring_write_rptr(sc, ring);
   1084  1.1      maya 	bwfm_pci_ring_write_wptr(sc, ring);
   1085  1.1      maya 
   1086  1.1      maya 	ring->ring = bwfm_pci_dmamem_alloc(sc, nitem * itemsz, 8);
   1087  1.1      maya 	if (ring->ring == NULL)
   1088  1.1      maya 		return ENOMEM;
   1089  1.1      maya 	bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
   1090  1.1      maya 	    *ring_mem + BWFM_RING_MEM_BASE_ADDR_LOW,
   1091  1.1      maya 	    BWFM_PCI_DMA_DVA(ring->ring) & 0xffffffff);
   1092  1.1      maya 	bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
   1093  1.1      maya 	    *ring_mem + BWFM_RING_MEM_BASE_ADDR_HIGH,
   1094  1.1      maya 	    BWFM_PCI_DMA_DVA(ring->ring) >> 32);
   1095  1.1      maya 	bus_space_write_2(sc->sc_tcm_iot, sc->sc_tcm_ioh,
   1096  1.1      maya 	    *ring_mem + BWFM_RING_MAX_ITEM, nitem);
   1097  1.1      maya 	bus_space_write_2(sc->sc_tcm_iot, sc->sc_tcm_ioh,
   1098  1.1      maya 	    *ring_mem + BWFM_RING_LEN_ITEMS, itemsz);
   1099  1.1      maya 	*ring_mem = *ring_mem + BWFM_RING_MEM_SZ;
   1100  1.1      maya 	return 0;
   1101  1.1      maya }
   1102  1.1      maya 
   1103  1.1      maya int
   1104  1.1      maya bwfm_pci_setup_flowring(struct bwfm_pci_softc *sc, struct bwfm_pci_msgring *ring,
   1105  1.1      maya     int nitem, size_t itemsz)
   1106  1.1      maya {
   1107  1.1      maya 	ring->w_ptr = 0;
   1108  1.1      maya 	ring->r_ptr = 0;
   1109  1.1      maya 	ring->nitem = nitem;
   1110  1.1      maya 	ring->itemsz = itemsz;
   1111  1.1      maya 	bwfm_pci_ring_write_rptr(sc, ring);
   1112  1.1      maya 	bwfm_pci_ring_write_wptr(sc, ring);
   1113  1.1      maya 
   1114  1.1      maya 	ring->ring = bwfm_pci_dmamem_alloc(sc, nitem * itemsz, 8);
   1115  1.1      maya 	if (ring->ring == NULL)
   1116  1.1      maya 		return ENOMEM;
   1117  1.1      maya 	return 0;
   1118  1.1      maya }
   1119  1.1      maya 
   1120  1.1      maya /* Ring helpers */
   1121  1.1      maya void
   1122  1.1      maya bwfm_pci_ring_bell(struct bwfm_pci_softc *sc,
   1123  1.1      maya     struct bwfm_pci_msgring *ring)
   1124  1.1      maya {
   1125  1.1      maya 	bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
   1126  1.1      maya 	    BWFM_PCI_PCIE2REG_H2D_MAILBOX, 1);
   1127  1.1      maya }
   1128  1.1      maya 
   1129  1.1      maya void
   1130  1.1      maya bwfm_pci_ring_update_rptr(struct bwfm_pci_softc *sc,
   1131  1.1      maya     struct bwfm_pci_msgring *ring)
   1132  1.1      maya {
   1133  1.1      maya 	if (sc->sc_dma_idx_sz == 0) {
   1134  1.1      maya 		ring->r_ptr = bus_space_read_2(sc->sc_tcm_iot,
   1135  1.1      maya 		    sc->sc_tcm_ioh, ring->r_idx_addr);
   1136  1.1      maya 	} else {
   1137  1.1      maya 		ring->r_ptr = *(uint16_t *)(BWFM_PCI_DMA_KVA(sc->sc_dma_idx_buf)
   1138  1.1      maya 		    + ring->r_idx_addr);
   1139  1.1      maya 	}
   1140  1.1      maya }
   1141  1.1      maya 
   1142  1.1      maya static u_int
   1143  1.1      maya if_rxr_get(struct if_rxring *rxr, unsigned int max)
   1144  1.1      maya {
   1145  1.1      maya 	u_int taken = MIN(max, (rxr->rxr_total - rxr->rxr_inuse));
   1146  1.1      maya 
   1147  1.1      maya 	KASSERTMSG(rxr->rxr_inuse + taken <= rxr->rxr_total,
   1148  1.1      maya 			"rxr->rxr_inuse: %d\n"
   1149  1.1      maya 			"taken: %d\n"
   1150  1.1      maya 			"rxr->rxr_total: %d\n",
   1151  1.1      maya 			rxr->rxr_inuse, taken, rxr->rxr_total);
   1152  1.1      maya 	rxr->rxr_inuse += taken;
   1153  1.1      maya 
   1154  1.1      maya 	return taken;
   1155  1.1      maya }
   1156  1.1      maya 
   1157  1.1      maya static void
   1158  1.1      maya if_rxr_put(struct if_rxring *rxr, unsigned int n)
   1159  1.1      maya {
   1160  1.1      maya 	KASSERTMSG(rxr->rxr_inuse >= n,
   1161  1.1      maya 			"rxr->rxr_inuse: %d\n"
   1162  1.1      maya 			"n: %d\n"
   1163  1.1      maya 			"rxr->rxr_total: %d\n",
   1164  1.1      maya 			rxr->rxr_inuse, n, rxr->rxr_total);
   1165  1.1      maya 
   1166  1.1      maya 	rxr->rxr_inuse -= n;
   1167  1.1      maya }
   1168  1.1      maya 
   1169  1.1      maya static void
   1170  1.1      maya if_rxr_init(struct if_rxring *rxr, unsigned int lwm __unused, unsigned int hwm)
   1171  1.1      maya {
   1172  1.1      maya 	(void) lwm;
   1173  1.1      maya 
   1174  1.1      maya 	rxr->rxr_total = hwm;
   1175  1.1      maya 	rxr->rxr_inuse = 0;
   1176  1.1      maya }
   1177  1.1      maya 
   1178  1.1      maya void
   1179  1.1      maya bwfm_pci_ring_update_wptr(struct bwfm_pci_softc *sc,
   1180  1.1      maya     struct bwfm_pci_msgring *ring)
   1181  1.1      maya {
   1182  1.1      maya 	if (sc->sc_dma_idx_sz == 0) {
   1183  1.1      maya 		ring->w_ptr = bus_space_read_2(sc->sc_tcm_iot,
   1184  1.1      maya 		    sc->sc_tcm_ioh, ring->w_idx_addr);
   1185  1.1      maya 	} else {
   1186  1.1      maya 		ring->w_ptr = *(uint16_t *)(BWFM_PCI_DMA_KVA(sc->sc_dma_idx_buf)
   1187  1.1      maya 		    + ring->w_idx_addr);
   1188  1.1      maya 	}
   1189  1.1      maya }
   1190  1.1      maya 
   1191  1.1      maya void
   1192  1.1      maya bwfm_pci_ring_write_rptr(struct bwfm_pci_softc *sc,
   1193  1.1      maya     struct bwfm_pci_msgring *ring)
   1194  1.1      maya {
   1195  1.1      maya 	if (sc->sc_dma_idx_sz == 0) {
   1196  1.1      maya 		bus_space_write_2(sc->sc_tcm_iot, sc->sc_tcm_ioh,
   1197  1.1      maya 		    ring->r_idx_addr, ring->r_ptr);
   1198  1.1      maya 	} else {
   1199  1.1      maya 		*(uint16_t *)(BWFM_PCI_DMA_KVA(sc->sc_dma_idx_buf)
   1200  1.1      maya 		    + ring->r_idx_addr) = ring->r_ptr;
   1201  1.1      maya 	}
   1202  1.1      maya }
   1203  1.1      maya 
   1204  1.1      maya void
   1205  1.1      maya bwfm_pci_ring_write_wptr(struct bwfm_pci_softc *sc,
   1206  1.1      maya     struct bwfm_pci_msgring *ring)
   1207  1.1      maya {
   1208  1.1      maya 	if (sc->sc_dma_idx_sz == 0) {
   1209  1.1      maya 		bus_space_write_2(sc->sc_tcm_iot, sc->sc_tcm_ioh,
   1210  1.1      maya 		    ring->w_idx_addr, ring->w_ptr);
   1211  1.1      maya 	} else {
   1212  1.1      maya 		*(uint16_t *)(BWFM_PCI_DMA_KVA(sc->sc_dma_idx_buf)
   1213  1.1      maya 		    + ring->w_idx_addr) = ring->w_ptr;
   1214  1.1      maya 	}
   1215  1.1      maya }
   1216  1.1      maya 
   1217  1.1      maya /*
   1218  1.1      maya  * Retrieve a free descriptor to put new stuff in, but don't commit
   1219  1.1      maya  * to it yet so we can rollback later if any error occurs.
   1220  1.1      maya  */
   1221  1.1      maya void *
   1222  1.1      maya bwfm_pci_ring_write_reserve(struct bwfm_pci_softc *sc,
   1223  1.1      maya     struct bwfm_pci_msgring *ring)
   1224  1.1      maya {
   1225  1.1      maya 	int available;
   1226  1.1      maya 	char *ret;
   1227  1.1      maya 
   1228  1.1      maya 	bwfm_pci_ring_update_rptr(sc, ring);
   1229  1.1      maya 
   1230  1.1      maya 	if (ring->r_ptr > ring->w_ptr)
   1231  1.1      maya 		available = ring->r_ptr - ring->w_ptr;
   1232  1.1      maya 	else
   1233  1.1      maya 		available = ring->r_ptr + (ring->nitem - ring->w_ptr);
   1234  1.1      maya 
   1235  1.1      maya 	if (available < 1)
   1236  1.1      maya 		return NULL;
   1237  1.1      maya 
   1238  1.1      maya 	ret = BWFM_PCI_DMA_KVA(ring->ring) + (ring->w_ptr * ring->itemsz);
   1239  1.1      maya 	ring->w_ptr += 1;
   1240  1.1      maya 	if (ring->w_ptr == ring->nitem)
   1241  1.1      maya 		ring->w_ptr = 0;
   1242  1.1      maya 	return ret;
   1243  1.1      maya }
   1244  1.1      maya 
   1245  1.1      maya void *
   1246  1.1      maya bwfm_pci_ring_write_reserve_multi(struct bwfm_pci_softc *sc,
   1247  1.1      maya     struct bwfm_pci_msgring *ring, int count, int *avail)
   1248  1.1      maya {
   1249  1.1      maya 	int available;
   1250  1.1      maya 	char *ret;
   1251  1.1      maya 
   1252  1.1      maya 	bwfm_pci_ring_update_rptr(sc, ring);
   1253  1.1      maya 
   1254  1.1      maya 	if (ring->r_ptr > ring->w_ptr)
   1255  1.1      maya 		available = ring->r_ptr - ring->w_ptr;
   1256  1.1      maya 	else
   1257  1.1      maya 		available = ring->r_ptr + (ring->nitem - ring->w_ptr);
   1258  1.1      maya 
   1259  1.1      maya 	if (available < 1)
   1260  1.1      maya 		return NULL;
   1261  1.1      maya 
   1262  1.1      maya 	ret = BWFM_PCI_DMA_KVA(ring->ring) + (ring->w_ptr * ring->itemsz);
   1263  1.3  riastrad 	*avail = uimin(count, available - 1);
   1264  1.1      maya 	if (*avail + ring->w_ptr > ring->nitem)
   1265  1.1      maya 		*avail = ring->nitem - ring->w_ptr;
   1266  1.1      maya 	ring->w_ptr += *avail;
   1267  1.1      maya 	if (ring->w_ptr == ring->nitem)
   1268  1.1      maya 		ring->w_ptr = 0;
   1269  1.1      maya 	return ret;
   1270  1.1      maya }
   1271  1.1      maya 
   1272  1.1      maya /*
   1273  1.1      maya  * Read number of descriptors available (submitted by the firmware)
   1274  1.1      maya  * and retrieve pointer to first descriptor.
   1275  1.1      maya  */
   1276  1.1      maya void *
   1277  1.1      maya bwfm_pci_ring_read_avail(struct bwfm_pci_softc *sc,
   1278  1.1      maya     struct bwfm_pci_msgring *ring, int *avail)
   1279  1.1      maya {
   1280  1.1      maya 	bwfm_pci_ring_update_wptr(sc, ring);
   1281  1.1      maya 
   1282  1.1      maya 	if (ring->w_ptr >= ring->r_ptr)
   1283  1.1      maya 		*avail = ring->w_ptr - ring->r_ptr;
   1284  1.1      maya 	else
   1285  1.1      maya 		*avail = ring->nitem - ring->r_ptr;
   1286  1.1      maya 
   1287  1.1      maya 	if (*avail == 0)
   1288  1.1      maya 		return NULL;
   1289  1.1      maya 
   1290  1.1      maya 	return BWFM_PCI_DMA_KVA(ring->ring) + (ring->r_ptr * ring->itemsz);
   1291  1.1      maya }
   1292  1.1      maya 
   1293  1.1      maya /*
   1294  1.1      maya  * Let firmware know we read N descriptors.
   1295  1.1      maya  */
   1296  1.1      maya void
   1297  1.1      maya bwfm_pci_ring_read_commit(struct bwfm_pci_softc *sc,
   1298  1.1      maya     struct bwfm_pci_msgring *ring, int nitem)
   1299  1.1      maya {
   1300  1.1      maya 	ring->r_ptr += nitem;
   1301  1.1      maya 	if (ring->r_ptr == ring->nitem)
   1302  1.1      maya 		ring->r_ptr = 0;
   1303  1.1      maya 	bwfm_pci_ring_write_rptr(sc, ring);
   1304  1.1      maya }
   1305  1.1      maya 
   1306  1.1      maya /*
   1307  1.1      maya  * Let firmware know that we submitted some descriptors.
   1308  1.1      maya  */
   1309  1.1      maya void
   1310  1.1      maya bwfm_pci_ring_write_commit(struct bwfm_pci_softc *sc,
   1311  1.1      maya     struct bwfm_pci_msgring *ring)
   1312  1.1      maya {
   1313  1.1      maya 	bwfm_pci_ring_write_wptr(sc, ring);
   1314  1.1      maya 	bwfm_pci_ring_bell(sc, ring);
   1315  1.1      maya }
   1316  1.1      maya 
   1317  1.1      maya /*
   1318  1.1      maya  * Rollback N descriptors in case we don't actually want
   1319  1.1      maya  * to commit to it.
   1320  1.1      maya  */
   1321  1.1      maya void
   1322  1.1      maya bwfm_pci_ring_write_cancel(struct bwfm_pci_softc *sc,
   1323  1.1      maya     struct bwfm_pci_msgring *ring, int nitem)
   1324  1.1      maya {
   1325  1.1      maya 	if (ring->w_ptr == 0)
   1326  1.1      maya 		ring->w_ptr = ring->nitem - nitem;
   1327  1.1      maya 	else
   1328  1.1      maya 		ring->w_ptr -= nitem;
   1329  1.1      maya }
   1330  1.1      maya 
   1331  1.1      maya /*
   1332  1.1      maya  * Foreach written descriptor on the ring, pass the descriptor to
   1333  1.1      maya  * a message handler and let the firmware know we handled it.
   1334  1.1      maya  */
   1335  1.1      maya void
   1336  1.1      maya bwfm_pci_ring_rx(struct bwfm_pci_softc *sc, struct bwfm_pci_msgring *ring)
   1337  1.1      maya {
   1338  1.1      maya 	char *buf;
   1339  1.1      maya 	int avail, processed;
   1340  1.1      maya 
   1341  1.1      maya again:
   1342  1.1      maya 	buf = bwfm_pci_ring_read_avail(sc, ring, &avail);
   1343  1.1      maya 	if (buf == NULL)
   1344  1.1      maya 		return;
   1345  1.1      maya 
   1346  1.1      maya 	processed = 0;
   1347  1.1      maya 	while (avail) {
   1348  1.1      maya 		bwfm_pci_msg_rx(sc, buf + sc->sc_rx_dataoffset);
   1349  1.1      maya 		buf += ring->itemsz;
   1350  1.1      maya 		processed++;
   1351  1.1      maya 		if (processed == 48) {
   1352  1.1      maya 			bwfm_pci_ring_read_commit(sc, ring, processed);
   1353  1.1      maya 			processed = 0;
   1354  1.1      maya 		}
   1355  1.1      maya 		avail--;
   1356  1.1      maya 	}
   1357  1.1      maya 	if (processed)
   1358  1.1      maya 		bwfm_pci_ring_read_commit(sc, ring, processed);
   1359  1.1      maya 	if (ring->r_ptr == 0)
   1360  1.1      maya 		goto again;
   1361  1.1      maya }
   1362  1.1      maya 
   1363  1.1      maya void
   1364  1.1      maya bwfm_pci_msg_rx(struct bwfm_pci_softc *sc, void *buf)
   1365  1.1      maya {
   1366  1.1      maya 	struct ifnet *ifp = sc->sc_sc.sc_ic.ic_ifp;
   1367  1.1      maya 	struct msgbuf_ioctl_resp_hdr *resp;
   1368  1.1      maya 	struct msgbuf_tx_status *tx;
   1369  1.1      maya 	struct msgbuf_rx_complete *rx;
   1370  1.1      maya 	struct msgbuf_rx_event *event;
   1371  1.1      maya 	struct msgbuf_common_hdr *msg;
   1372  1.1      maya 	struct msgbuf_flowring_create_resp *fcr;
   1373  1.1      maya 	struct msgbuf_flowring_delete_resp *fdr;
   1374  1.1      maya 	struct bwfm_pci_msgring *ring;
   1375  1.1      maya 	struct mbuf *m;
   1376  1.1      maya 	int flowid;
   1377  1.1      maya 
   1378  1.1      maya 	msg = (struct msgbuf_common_hdr *)buf;
   1379  1.1      maya 	switch (msg->msgtype)
   1380  1.1      maya 	{
   1381  1.1      maya 	case MSGBUF_TYPE_FLOW_RING_CREATE_CMPLT:
   1382  1.1      maya 		fcr = (struct msgbuf_flowring_create_resp *)buf;
   1383  1.1      maya 		flowid = letoh16(fcr->compl_hdr.flow_ring_id);
   1384  1.1      maya 		if (flowid < 2)
   1385  1.1      maya 			break;
   1386  1.1      maya 		flowid -= 2;
   1387  1.1      maya 		if (flowid >= sc->sc_max_flowrings)
   1388  1.1      maya 			break;
   1389  1.1      maya 		ring = &sc->sc_flowrings[flowid];
   1390  1.1      maya 		if (ring->status != RING_OPENING)
   1391  1.1      maya 			break;
   1392  1.1      maya 		if (fcr->compl_hdr.status) {
   1393  1.1      maya 			printf("%s: failed to open flowring %d\n",
   1394  1.1      maya 			    DEVNAME(sc), flowid);
   1395  1.1      maya 			ring->status = RING_CLOSED;
   1396  1.1      maya 			if (ring->m) {
   1397  1.1      maya 				m_freem(ring->m);
   1398  1.1      maya 				ring->m = NULL;
   1399  1.1      maya 			}
   1400  1.1      maya 			ifp->if_flags &= ~IFF_OACTIVE;
   1401  1.1      maya 			ifp->if_start(ifp);
   1402  1.1      maya 			break;
   1403  1.1      maya 		}
   1404  1.1      maya 		ring->status = RING_OPEN;
   1405  1.1      maya 		if (ring->m != NULL) {
   1406  1.1      maya 			m = ring->m;
   1407  1.1      maya 			ring->m = NULL;
   1408  1.2  riastrad 			if (bwfm_pci_txdata(&sc->sc_sc, &m))
   1409  1.1      maya 				m_freem(ring->m);
   1410  1.1      maya 		}
   1411  1.1      maya 		ifp->if_flags &= ~IFF_OACTIVE;
   1412  1.1      maya 		ifp->if_start(ifp);
   1413  1.1      maya 		break;
   1414  1.1      maya 	case MSGBUF_TYPE_FLOW_RING_DELETE_CMPLT:
   1415  1.1      maya 		fdr = (struct msgbuf_flowring_delete_resp *)buf;
   1416  1.1      maya 		flowid = letoh16(fdr->compl_hdr.flow_ring_id);
   1417  1.1      maya 		if (flowid < 2)
   1418  1.1      maya 			break;
   1419  1.1      maya 		flowid -= 2;
   1420  1.1      maya 		if (flowid >= sc->sc_max_flowrings)
   1421  1.1      maya 			break;
   1422  1.1      maya 		ring = &sc->sc_flowrings[flowid];
   1423  1.1      maya 		if (ring->status != RING_CLOSING)
   1424  1.1      maya 			break;
   1425  1.1      maya 		if (fdr->compl_hdr.status) {
   1426  1.1      maya 			printf("%s: failed to delete flowring %d\n",
   1427  1.1      maya 			    DEVNAME(sc), flowid);
   1428  1.1      maya 			break;
   1429  1.1      maya 		}
   1430  1.1      maya 		bwfm_pci_dmamem_free(sc, ring->ring);
   1431  1.1      maya 		ring->status = RING_CLOSED;
   1432  1.1      maya 		break;
   1433  1.1      maya 	case MSGBUF_TYPE_IOCTLPTR_REQ_ACK:
   1434  1.1      maya 		break;
   1435  1.1      maya 	case MSGBUF_TYPE_IOCTL_CMPLT:
   1436  1.1      maya 		resp = (struct msgbuf_ioctl_resp_hdr *)buf;
   1437  1.1      maya 		sc->sc_ioctl_resp_pktid = letoh32(resp->msg.request_id);
   1438  1.1      maya 		sc->sc_ioctl_resp_ret_len = letoh16(resp->resp_len);
   1439  1.1      maya 		sc->sc_ioctl_resp_status = letoh16(resp->compl_hdr.status);
   1440  1.1      maya 		if_rxr_put(&sc->sc_ioctl_ring, 1);
   1441  1.1      maya 		bwfm_pci_fill_rx_rings(sc);
   1442  1.1      maya 		wakeup(&sc->sc_ioctl_buf);
   1443  1.1      maya 		break;
   1444  1.1      maya 	case MSGBUF_TYPE_WL_EVENT:
   1445  1.1      maya 		event = (struct msgbuf_rx_event *)buf;
   1446  1.1      maya 		m = bwfm_pci_pktid_free(sc, &sc->sc_rx_pkts,
   1447  1.1      maya 		    letoh32(event->msg.request_id));
   1448  1.1      maya 		if (m == NULL)
   1449  1.1      maya 			break;
   1450  1.1      maya 		m_adj(m, sc->sc_rx_dataoffset);
   1451  1.1      maya 		m->m_len = m->m_pkthdr.len = letoh16(event->event_data_len);
   1452  1.1      maya 		bwfm_rx(&sc->sc_sc, m);
   1453  1.1      maya 		if_rxr_put(&sc->sc_event_ring, 1);
   1454  1.1      maya 		bwfm_pci_fill_rx_rings(sc);
   1455  1.1      maya 		break;
   1456  1.1      maya 	case MSGBUF_TYPE_TX_STATUS:
   1457  1.1      maya 		tx = (struct msgbuf_tx_status *)buf;
   1458  1.1      maya 		m = bwfm_pci_pktid_free(sc, &sc->sc_tx_pkts,
   1459  1.1      maya 		    letoh32(tx->msg.request_id));
   1460  1.1      maya 		if (m == NULL)
   1461  1.1      maya 			break;
   1462  1.1      maya 		m_freem(m);
   1463  1.1      maya 		if (sc->sc_tx_pkts_full) {
   1464  1.1      maya 			sc->sc_tx_pkts_full = 0;
   1465  1.1      maya 			ifp->if_flags &= ~IFF_OACTIVE;
   1466  1.1      maya 			ifp->if_start(ifp);
   1467  1.1      maya 		}
   1468  1.1      maya 		break;
   1469  1.1      maya 	case MSGBUF_TYPE_RX_CMPLT:
   1470  1.1      maya 		rx = (struct msgbuf_rx_complete *)buf;
   1471  1.1      maya 		m = bwfm_pci_pktid_free(sc, &sc->sc_rx_pkts,
   1472  1.1      maya 		    letoh32(rx->msg.request_id));
   1473  1.1      maya 		if (m == NULL)
   1474  1.1      maya 			break;
   1475  1.1      maya 		if (letoh16(rx->data_offset))
   1476  1.1      maya 			m_adj(m, letoh16(rx->data_offset));
   1477  1.1      maya 		else if (sc->sc_rx_dataoffset)
   1478  1.1      maya 			m_adj(m, sc->sc_rx_dataoffset);
   1479  1.1      maya 		m->m_len = m->m_pkthdr.len = letoh16(rx->data_len);
   1480  1.1      maya 		bwfm_rx(&sc->sc_sc, m);
   1481  1.1      maya 		if_rxr_put(&sc->sc_rxbuf_ring, 1);
   1482  1.1      maya 		bwfm_pci_fill_rx_rings(sc);
   1483  1.1      maya 		break;
   1484  1.1      maya 	default:
   1485  1.1      maya 		printf("%s: msgtype 0x%08x\n", __func__, msg->msgtype);
   1486  1.1      maya 		break;
   1487  1.1      maya 	}
   1488  1.1      maya }
   1489  1.1      maya 
   1490  1.1      maya /* Bus core helpers */
   1491  1.1      maya void
   1492  1.1      maya bwfm_pci_select_core(struct bwfm_pci_softc *sc, int id)
   1493  1.1      maya {
   1494  1.1      maya 	struct bwfm_softc *bwfm = (void *)sc;
   1495  1.1      maya 	struct bwfm_core *core;
   1496  1.1      maya 
   1497  1.1      maya 	core = bwfm_chip_get_core(bwfm, id);
   1498  1.1      maya 	if (core == NULL) {
   1499  1.1      maya 		printf("%s: could not find core to select", DEVNAME(sc));
   1500  1.1      maya 		return;
   1501  1.1      maya 	}
   1502  1.1      maya 
   1503  1.1      maya 	pci_conf_write(sc->sc_pc, sc->sc_tag,
   1504  1.1      maya 	    BWFM_PCI_BAR0_WINDOW, core->co_base);
   1505  1.1      maya 	if (pci_conf_read(sc->sc_pc, sc->sc_tag,
   1506  1.1      maya 	    BWFM_PCI_BAR0_WINDOW) != core->co_base)
   1507  1.1      maya 		pci_conf_write(sc->sc_pc, sc->sc_tag,
   1508  1.1      maya 		    BWFM_PCI_BAR0_WINDOW, core->co_base);
   1509  1.1      maya }
   1510  1.1      maya 
   1511  1.1      maya uint32_t
   1512  1.1      maya bwfm_pci_buscore_read(struct bwfm_softc *bwfm, uint32_t reg)
   1513  1.1      maya {
   1514  1.1      maya 	struct bwfm_pci_softc *sc = (void *)bwfm;
   1515  1.1      maya 	uint32_t page, offset;
   1516  1.1      maya 
   1517  1.1      maya 	page = reg & ~(BWFM_PCI_BAR0_REG_SIZE - 1);
   1518  1.1      maya 	offset = reg & (BWFM_PCI_BAR0_REG_SIZE - 1);
   1519  1.1      maya 	pci_conf_write(sc->sc_pc, sc->sc_tag, BWFM_PCI_BAR0_WINDOW, page);
   1520  1.1      maya 	return bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh, offset);
   1521  1.1      maya }
   1522  1.1      maya 
   1523  1.1      maya void
   1524  1.1      maya bwfm_pci_buscore_write(struct bwfm_softc *bwfm, uint32_t reg, uint32_t val)
   1525  1.1      maya {
   1526  1.1      maya 	struct bwfm_pci_softc *sc = (void *)bwfm;
   1527  1.1      maya 	uint32_t page, offset;
   1528  1.1      maya 
   1529  1.1      maya 	page = reg & ~(BWFM_PCI_BAR0_REG_SIZE - 1);
   1530  1.1      maya 	offset = reg & (BWFM_PCI_BAR0_REG_SIZE - 1);
   1531  1.1      maya 	pci_conf_write(sc->sc_pc, sc->sc_tag, BWFM_PCI_BAR0_WINDOW, page);
   1532  1.1      maya 	bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh, offset, val);
   1533  1.1      maya }
   1534  1.1      maya 
   1535  1.1      maya int
   1536  1.1      maya bwfm_pci_buscore_prepare(struct bwfm_softc *bwfm)
   1537  1.1      maya {
   1538  1.1      maya 	return 0;
   1539  1.1      maya }
   1540  1.1      maya 
   1541  1.1      maya int
   1542  1.1      maya bwfm_pci_buscore_reset(struct bwfm_softc *bwfm)
   1543  1.1      maya {
   1544  1.1      maya 	struct bwfm_pci_softc *sc = (void *)bwfm;
   1545  1.1      maya 	struct bwfm_core *core;
   1546  1.1      maya 	uint32_t reg;
   1547  1.1      maya 	int i;
   1548  1.1      maya 
   1549  1.1      maya 	bwfm_pci_select_core(sc, BWFM_AGENT_CORE_PCIE2);
   1550  1.1      maya 	reg = pci_conf_read(sc->sc_pc, sc->sc_tag,
   1551  1.1      maya 	    BWFM_PCI_CFGREG_LINK_STATUS_CTRL);
   1552  1.1      maya 	pci_conf_write(sc->sc_pc, sc->sc_tag, BWFM_PCI_CFGREG_LINK_STATUS_CTRL,
   1553  1.1      maya 	    reg & ~BWFM_PCI_CFGREG_LINK_STATUS_CTRL_ASPM_ENAB);
   1554  1.1      maya 
   1555  1.1      maya 	bwfm_pci_select_core(sc, BWFM_AGENT_CORE_CHIPCOMMON);
   1556  1.1      maya 	bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
   1557  1.1      maya 	    BWFM_CHIP_REG_WATCHDOG, 4);
   1558  1.1      maya 	delay(100 * 1000);
   1559  1.1      maya 
   1560  1.1      maya 	bwfm_pci_select_core(sc, BWFM_AGENT_CORE_PCIE2);
   1561  1.1      maya 	pci_conf_write(sc->sc_pc, sc->sc_tag,
   1562  1.1      maya 	    BWFM_PCI_CFGREG_LINK_STATUS_CTRL, reg);
   1563  1.1      maya 
   1564  1.1      maya 	core = bwfm_chip_get_core(bwfm, BWFM_AGENT_CORE_PCIE2);
   1565  1.1      maya 	if (core->co_rev <= 13) {
   1566  1.1      maya 		uint16_t cfg_offset[] = {
   1567  1.1      maya 		    BWFM_PCI_CFGREG_STATUS_CMD,
   1568  1.1      maya 		    BWFM_PCI_CFGREG_PM_CSR,
   1569  1.1      maya 		    BWFM_PCI_CFGREG_MSI_CAP,
   1570  1.1      maya 		    BWFM_PCI_CFGREG_MSI_ADDR_L,
   1571  1.1      maya 		    BWFM_PCI_CFGREG_MSI_ADDR_H,
   1572  1.1      maya 		    BWFM_PCI_CFGREG_MSI_DATA,
   1573  1.1      maya 		    BWFM_PCI_CFGREG_LINK_STATUS_CTRL2,
   1574  1.1      maya 		    BWFM_PCI_CFGREG_RBAR_CTRL,
   1575  1.1      maya 		    BWFM_PCI_CFGREG_PML1_SUB_CTRL1,
   1576  1.1      maya 		    BWFM_PCI_CFGREG_REG_BAR2_CONFIG,
   1577  1.1      maya 		    BWFM_PCI_CFGREG_REG_BAR3_CONFIG,
   1578  1.1      maya 		};
   1579  1.1      maya 
   1580  1.1      maya 		for (i = 0; i < nitems(cfg_offset); i++) {
   1581  1.1      maya 			bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
   1582  1.1      maya 			    BWFM_PCI_PCIE2REG_CONFIGADDR, cfg_offset[i]);
   1583  1.1      maya 			reg = bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh,
   1584  1.1      maya 			    BWFM_PCI_PCIE2REG_CONFIGDATA);
   1585  1.1      maya 			DPRINTFN(3, ("%s: config offset 0x%04x, value 0x%04x\n",
   1586  1.1      maya 			    DEVNAME(sc), cfg_offset[i], reg));
   1587  1.1      maya 			bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
   1588  1.1      maya 			    BWFM_PCI_PCIE2REG_CONFIGDATA, reg);
   1589  1.1      maya 		}
   1590  1.1      maya 	}
   1591  1.1      maya 
   1592  1.1      maya 	reg = bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh,
   1593  1.1      maya 	    BWFM_PCI_PCIE2REG_MAILBOXINT);
   1594  1.1      maya 	if (reg != 0xffffffff)
   1595  1.1      maya 		bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
   1596  1.1      maya 		    BWFM_PCI_PCIE2REG_MAILBOXINT, reg);
   1597  1.1      maya 
   1598  1.1      maya 	return 0;
   1599  1.1      maya }
   1600  1.1      maya 
   1601  1.1      maya void
   1602  1.1      maya bwfm_pci_buscore_activate(struct bwfm_softc *bwfm, const uint32_t rstvec)
   1603  1.1      maya {
   1604  1.1      maya 	struct bwfm_pci_softc *sc = (void *)bwfm;
   1605  1.1      maya 	bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh, 0, rstvec);
   1606  1.1      maya }
   1607  1.1      maya 
   1608  1.1      maya static int bwfm_pci_prio2fifo[8] = {
   1609  1.1      maya 	1, /* best effort */
   1610  1.1      maya 	0, /* IPTOS_PREC_IMMEDIATE */
   1611  1.1      maya 	0, /* IPTOS_PREC_PRIORITY */
   1612  1.1      maya 	1, /* IPTOS_PREC_FLASH */
   1613  1.1      maya 	2, /* IPTOS_PREC_FLASHOVERRIDE */
   1614  1.1      maya 	2, /* IPTOS_PREC_CRITIC_ECP */
   1615  1.1      maya 	3, /* IPTOS_PREC_INTERNETCONTROL */
   1616  1.1      maya 	3, /* IPTOS_PREC_NETCONTROL */
   1617  1.1      maya };
   1618  1.1      maya 
   1619  1.1      maya int
   1620  1.1      maya bwfm_pci_flowring_lookup(struct bwfm_pci_softc *sc, struct mbuf *m)
   1621  1.1      maya {
   1622  1.1      maya 	struct ieee80211com *ic = &sc->sc_sc.sc_ic;
   1623  1.1      maya 	uint8_t *da = mtod(m, uint8_t *);
   1624  1.1      maya 	struct ether_header *eh;
   1625  1.1      maya 	int flowid, prio, fifo;
   1626  1.1      maya 	int i, found, ac;
   1627  1.1      maya 
   1628  1.1      maya 	/* No QoS for EAPOL frames. */
   1629  1.1      maya 	eh = mtod(m, struct ether_header *);
   1630  1.1      maya 	ac = (eh->ether_type != htons(ETHERTYPE_PAE)) ?
   1631  1.1      maya 	    M_WME_GETAC(m) : WME_AC_BE;
   1632  1.1      maya 
   1633  1.1      maya 	prio = ac;
   1634  1.1      maya 	fifo = bwfm_pci_prio2fifo[prio];
   1635  1.1      maya 
   1636  1.1      maya 	switch (ic->ic_opmode)
   1637  1.1      maya 	{
   1638  1.1      maya 	case IEEE80211_M_STA:
   1639  1.1      maya 		flowid = fifo;
   1640  1.1      maya 		break;
   1641  1.1      maya #ifndef IEEE80211_STA_ONLY
   1642  1.1      maya 	case IEEE80211_M_HOSTAP:
   1643  1.1      maya 		if (ETHER_IS_MULTICAST(da))
   1644  1.1      maya 			da = __UNCONST(etherbroadcastaddr);
   1645  1.1      maya 		flowid = da[5] * 2 + fifo;
   1646  1.1      maya 		break;
   1647  1.1      maya #endif
   1648  1.1      maya 	default:
   1649  1.1      maya 		printf("%s: state not supported\n", DEVNAME(sc));
   1650  1.1      maya 		return ENOBUFS;
   1651  1.1      maya 	}
   1652  1.1      maya 
   1653  1.1      maya 	found = 0;
   1654  1.1      maya 	flowid = flowid % sc->sc_max_flowrings;
   1655  1.1      maya 	for (i = 0; i < sc->sc_max_flowrings; i++) {
   1656  1.1      maya 		if (ic->ic_opmode == IEEE80211_M_STA &&
   1657  1.1      maya 		    sc->sc_flowrings[flowid].status >= RING_OPEN &&
   1658  1.1      maya 		    sc->sc_flowrings[flowid].fifo == fifo) {
   1659  1.1      maya 			found = 1;
   1660  1.1      maya 			break;
   1661  1.1      maya 		}
   1662  1.1      maya #ifndef IEEE80211_STA_ONLY
   1663  1.1      maya 		if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
   1664  1.1      maya 		    sc->sc_flowrings[flowid].status >= RING_OPEN &&
   1665  1.1      maya 		    sc->sc_flowrings[flowid].fifo == fifo &&
   1666  1.1      maya 		    !memcmp(sc->sc_flowrings[flowid].mac, da, ETHER_ADDR_LEN)) {
   1667  1.1      maya 			found = 1;
   1668  1.1      maya 			break;
   1669  1.1      maya 		}
   1670  1.1      maya #endif
   1671  1.1      maya 		flowid = (flowid + 1) % sc->sc_max_flowrings;
   1672  1.1      maya 	}
   1673  1.1      maya 
   1674  1.1      maya 	if (found)
   1675  1.1      maya 		return flowid;
   1676  1.1      maya 
   1677  1.1      maya 	return -1;
   1678  1.1      maya }
   1679  1.1      maya 
   1680  1.1      maya void
   1681  1.1      maya bwfm_pci_flowring_create(struct bwfm_pci_softc *sc, struct mbuf *m)
   1682  1.1      maya {
   1683  1.1      maya 	struct ieee80211com *ic = &sc->sc_sc.sc_ic;
   1684  1.1      maya 	struct bwfm_cmd_flowring_create * cmd;
   1685  1.1      maya 	uint8_t *da = mtod(m, uint8_t *);
   1686  1.1      maya 	struct ether_header *eh;
   1687  1.1      maya 	struct bwfm_pci_msgring *ring;
   1688  1.1      maya 	int flowid, prio, fifo;
   1689  1.1      maya 	int i, found, ac;
   1690  1.1      maya 
   1691  1.1      maya 	cmd = pool_get(&sc->sc_flowring_pool, PR_NOWAIT);
   1692  1.1      maya 	if (__predict_false(cmd == NULL))
   1693  1.1      maya 		return;
   1694  1.1      maya 
   1695  1.1      maya 	/* No QoS for EAPOL frames. */
   1696  1.1      maya 	eh = mtod(m, struct ether_header *);
   1697  1.1      maya 	ac = (eh->ether_type != htons(ETHERTYPE_PAE)) ?
   1698  1.1      maya 	    M_WME_GETAC(m) : WME_AC_BE;
   1699  1.1      maya 
   1700  1.1      maya 	prio = ac;
   1701  1.1      maya 	fifo = bwfm_pci_prio2fifo[prio];
   1702  1.1      maya 
   1703  1.1      maya 	switch (ic->ic_opmode)
   1704  1.1      maya 	{
   1705  1.1      maya 	case IEEE80211_M_STA:
   1706  1.1      maya 		flowid = fifo;
   1707  1.1      maya 		break;
   1708  1.1      maya #ifndef IEEE80211_STA_ONLY
   1709  1.1      maya 	case IEEE80211_M_HOSTAP:
   1710  1.1      maya 		if (ETHER_IS_MULTICAST(da))
   1711  1.1      maya 			da = __UNCONST(etherbroadcastaddr);
   1712  1.1      maya 		flowid = da[5] * 2 + fifo;
   1713  1.1      maya 		break;
   1714  1.1      maya #endif
   1715  1.1      maya 	default:
   1716  1.1      maya 		printf("%s: state not supported\n", DEVNAME(sc));
   1717  1.1      maya 		return;
   1718  1.1      maya 	}
   1719  1.1      maya 
   1720  1.1      maya 	found = 0;
   1721  1.1      maya 	flowid = flowid % sc->sc_max_flowrings;
   1722  1.1      maya 	for (i = 0; i < sc->sc_max_flowrings; i++) {
   1723  1.1      maya 		ring = &sc->sc_flowrings[flowid];
   1724  1.1      maya 		if (ring->status == RING_CLOSED) {
   1725  1.1      maya 			ring->status = RING_OPENING;
   1726  1.1      maya 			found = 1;
   1727  1.1      maya 			break;
   1728  1.1      maya 		}
   1729  1.1      maya 		flowid = (flowid + 1) % sc->sc_max_flowrings;
   1730  1.1      maya 	}
   1731  1.1      maya 
   1732  1.1      maya 	/*
   1733  1.1      maya 	 * We cannot recover from that so far.  Only a stop/init
   1734  1.1      maya 	 * cycle can revive this if it ever happens at all.
   1735  1.1      maya 	 */
   1736  1.1      maya 	if (!found) {
   1737  1.1      maya 		printf("%s: no flowring available\n", DEVNAME(sc));
   1738  1.1      maya 		return;
   1739  1.1      maya 	}
   1740  1.1      maya 
   1741  1.1      maya 	cmd->sc = sc;
   1742  1.1      maya 	cmd->m = m;
   1743  1.1      maya 	cmd->prio = prio;
   1744  1.1      maya 	cmd->flowid = flowid;
   1745  1.1      maya 	workqueue_enqueue(sc->flowring_wq, &cmd->wq_cookie, NULL);
   1746  1.1      maya }
   1747  1.1      maya 
   1748  1.1      maya void
   1749  1.1      maya bwfm_pci_flowring_create_cb(struct work *wk, void *arg) //(struct bwfm_softc *bwfm, void *arg)
   1750  1.1      maya {
   1751  1.1      maya 	struct bwfm_cmd_flowring_create *cmd = container_of(wk, struct bwfm_cmd_flowring_create, wq_cookie);
   1752  1.1      maya 	struct bwfm_pci_softc *sc = cmd->sc; // (void *)bwfm;
   1753  1.1      maya 	struct ieee80211com *ic = &sc->sc_sc.sc_ic;
   1754  1.1      maya 	struct msgbuf_tx_flowring_create_req *req;
   1755  1.1      maya 	struct bwfm_pci_msgring *ring;
   1756  1.1      maya 	uint8_t *da, *sa;
   1757  1.1      maya 
   1758  1.1      maya 	da = mtod(cmd->m, char *) + 0 * ETHER_ADDR_LEN;
   1759  1.1      maya 	sa = mtod(cmd->m, char *) + 1 * ETHER_ADDR_LEN;
   1760  1.1      maya 
   1761  1.1      maya 	ring = &sc->sc_flowrings[cmd->flowid];
   1762  1.1      maya 	if (ring->status != RING_OPENING) {
   1763  1.1      maya 		printf("%s: flowring not opening\n", DEVNAME(sc));
   1764  1.1      maya 		return;
   1765  1.1      maya 	}
   1766  1.1      maya 
   1767  1.1      maya 	if (bwfm_pci_setup_flowring(sc, ring, 512, 48)) {
   1768  1.1      maya 		printf("%s: cannot setup flowring\n", DEVNAME(sc));
   1769  1.1      maya 		return;
   1770  1.1      maya 	}
   1771  1.1      maya 
   1772  1.1      maya 	req = bwfm_pci_ring_write_reserve(sc, &sc->sc_ctrl_submit);
   1773  1.1      maya 	if (req == NULL) {
   1774  1.1      maya 		printf("%s: cannot reserve for flowring\n", DEVNAME(sc));
   1775  1.1      maya 		return;
   1776  1.1      maya 	}
   1777  1.1      maya 
   1778  1.1      maya 	ring->status = RING_OPENING;
   1779  1.1      maya 	ring->fifo = bwfm_pci_prio2fifo[cmd->prio];
   1780  1.1      maya 	ring->m = cmd->m;
   1781  1.1      maya 	memcpy(ring->mac, da, ETHER_ADDR_LEN);
   1782  1.1      maya #ifndef IEEE80211_STA_ONLY
   1783  1.1      maya 	if (ic->ic_opmode == IEEE80211_M_HOSTAP && ETHER_IS_MULTICAST(da))
   1784  1.1      maya 		memcpy(ring->mac, etherbroadcastaddr, ETHER_ADDR_LEN);
   1785  1.1      maya #endif
   1786  1.1      maya 
   1787  1.1      maya 	req->msg.msgtype = MSGBUF_TYPE_FLOW_RING_CREATE;
   1788  1.1      maya 	req->msg.ifidx = 0;
   1789  1.1      maya 	req->msg.request_id = 0;
   1790  1.1      maya 	req->tid = bwfm_pci_prio2fifo[cmd->prio];
   1791  1.1      maya 	req->flow_ring_id = letoh16(cmd->flowid + 2);
   1792  1.1      maya 	memcpy(req->da, da, ETHER_ADDR_LEN);
   1793  1.1      maya 	memcpy(req->sa, sa, ETHER_ADDR_LEN);
   1794  1.1      maya 	req->flow_ring_addr.high_addr =
   1795  1.1      maya 	    letoh32(BWFM_PCI_DMA_DVA(ring->ring) >> 32);
   1796  1.1      maya 	req->flow_ring_addr.low_addr =
   1797  1.1      maya 	    letoh32(BWFM_PCI_DMA_DVA(ring->ring) & 0xffffffff);
   1798  1.1      maya 	req->max_items = letoh16(512);
   1799  1.1      maya 	req->len_item = letoh16(48);
   1800  1.1      maya 
   1801  1.1      maya 	bwfm_pci_ring_write_commit(sc, &sc->sc_ctrl_submit);
   1802  1.1      maya 	pool_put(&sc->sc_flowring_pool, cmd);
   1803  1.1      maya }
   1804  1.1      maya 
   1805  1.1      maya void
   1806  1.1      maya bwfm_pci_flowring_delete(struct bwfm_pci_softc *sc, int flowid)
   1807  1.1      maya {
   1808  1.1      maya 	struct msgbuf_tx_flowring_delete_req *req;
   1809  1.1      maya 	struct bwfm_pci_msgring *ring;
   1810  1.1      maya 
   1811  1.1      maya 	ring = &sc->sc_flowrings[flowid];
   1812  1.1      maya 	if (ring->status != RING_OPEN) {
   1813  1.1      maya 		printf("%s: flowring not open\n", DEVNAME(sc));
   1814  1.1      maya 		return;
   1815  1.1      maya 	}
   1816  1.1      maya 
   1817  1.1      maya 	req = bwfm_pci_ring_write_reserve(sc, &sc->sc_ctrl_submit);
   1818  1.1      maya 	if (req == NULL) {
   1819  1.1      maya 		printf("%s: cannot reserve for flowring\n", DEVNAME(sc));
   1820  1.1      maya 		return;
   1821  1.1      maya 	}
   1822  1.1      maya 
   1823  1.1      maya 	ring->status = RING_CLOSING;
   1824  1.1      maya 
   1825  1.1      maya 	req->msg.msgtype = MSGBUF_TYPE_FLOW_RING_DELETE;
   1826  1.1      maya 	req->msg.ifidx = 0;
   1827  1.1      maya 	req->msg.request_id = 0;
   1828  1.1      maya 	req->flow_ring_id = letoh16(flowid + 2);
   1829  1.1      maya 	req->reason = 0;
   1830  1.1      maya 
   1831  1.1      maya 	bwfm_pci_ring_write_commit(sc, &sc->sc_ctrl_submit);
   1832  1.1      maya }
   1833  1.1      maya 
   1834  1.1      maya void
   1835  1.1      maya bwfm_pci_stop(struct bwfm_softc *bwfm)
   1836  1.1      maya {
   1837  1.1      maya 	struct bwfm_pci_softc *sc = (void *)bwfm;
   1838  1.1      maya 	struct bwfm_pci_msgring *ring;
   1839  1.1      maya 	int i;
   1840  1.1      maya 
   1841  1.1      maya 	for (i = 0; i < sc->sc_max_flowrings; i++) {
   1842  1.1      maya 		ring = &sc->sc_flowrings[i];
   1843  1.1      maya 		if (ring->status == RING_OPEN)
   1844  1.1      maya 			bwfm_pci_flowring_delete(sc, i);
   1845  1.1      maya 	}
   1846  1.1      maya }
   1847  1.1      maya 
   1848  1.1      maya int
   1849  1.1      maya bwfm_pci_txcheck(struct bwfm_softc *bwfm)
   1850  1.1      maya {
   1851  1.1      maya 	struct bwfm_pci_softc *sc = (void *)bwfm;
   1852  1.1      maya 	struct bwfm_pci_msgring *ring;
   1853  1.1      maya 	int i;
   1854  1.1      maya 
   1855  1.1      maya 	/* If we are transitioning, we cannot send. */
   1856  1.1      maya 	for (i = 0; i < sc->sc_max_flowrings; i++) {
   1857  1.1      maya 		ring = &sc->sc_flowrings[i];
   1858  1.1      maya 		if (ring->status == RING_OPENING)
   1859  1.1      maya 			return ENOBUFS;
   1860  1.1      maya 	}
   1861  1.1      maya 
   1862  1.1      maya 	if (bwfm_pci_pktid_avail(sc, &sc->sc_tx_pkts)) {
   1863  1.1      maya 		sc->sc_tx_pkts_full = 1;
   1864  1.1      maya 		return ENOBUFS;
   1865  1.1      maya 	}
   1866  1.1      maya 
   1867  1.1      maya 	return 0;
   1868  1.1      maya }
   1869  1.1      maya 
   1870  1.1      maya int
   1871  1.2  riastrad bwfm_pci_txdata(struct bwfm_softc *bwfm, struct mbuf **mp)
   1872  1.1      maya {
   1873  1.1      maya 	struct bwfm_pci_softc *sc = (void *)bwfm;
   1874  1.1      maya 	struct bwfm_pci_msgring *ring;
   1875  1.1      maya 	struct msgbuf_tx_msghdr *tx;
   1876  1.1      maya 	uint32_t pktid;
   1877  1.1      maya 	paddr_t paddr;
   1878  1.1      maya 	struct ether_header *eh;
   1879  1.1      maya 	int flowid, ret, ac;
   1880  1.1      maya 
   1881  1.2  riastrad 	flowid = bwfm_pci_flowring_lookup(sc, *mp);
   1882  1.1      maya 	if (flowid < 0) {
   1883  1.1      maya 		/*
   1884  1.1      maya 		 * We cannot send the packet right now as there is
   1885  1.1      maya 		 * no flowring yet.  The flowring will be created
   1886  1.1      maya 		 * asynchronously.  While the ring is transitioning
   1887  1.1      maya 		 * the TX check will tell the upper layers that we
   1888  1.1      maya 		 * cannot send packets right now.  When the flowring
   1889  1.1      maya 		 * is created the queue will be restarted and this
   1890  1.1      maya 		 * mbuf will be transmitted.
   1891  1.1      maya 		 */
   1892  1.2  riastrad 		bwfm_pci_flowring_create(sc, *mp);
   1893  1.1      maya 		return 0;
   1894  1.1      maya 	}
   1895  1.1      maya 
   1896  1.1      maya 	ring = &sc->sc_flowrings[flowid];
   1897  1.1      maya 	if (ring->status == RING_OPENING ||
   1898  1.1      maya 	    ring->status == RING_CLOSING) {
   1899  1.1      maya 		printf("%s: tried to use a flow that was "
   1900  1.1      maya 		    "transitioning in status %d\n",
   1901  1.1      maya 		    DEVNAME(sc), ring->status);
   1902  1.1      maya 		return ENOBUFS;
   1903  1.1      maya 	}
   1904  1.1      maya 
   1905  1.1      maya 	tx = bwfm_pci_ring_write_reserve(sc, ring);
   1906  1.1      maya 	if (tx == NULL)
   1907  1.1      maya 		return ENOBUFS;
   1908  1.1      maya 
   1909  1.1      maya 	/* No QoS for EAPOL frames. */
   1910  1.2  riastrad 	eh = mtod(*mp, struct ether_header *);
   1911  1.1      maya 	ac = (eh->ether_type != htons(ETHERTYPE_PAE)) ?
   1912  1.2  riastrad 	    M_WME_GETAC(*mp) : WME_AC_BE;
   1913  1.1      maya 
   1914  1.1      maya 	memset(tx, 0, sizeof(*tx));
   1915  1.1      maya 	tx->msg.msgtype = MSGBUF_TYPE_TX_POST;
   1916  1.1      maya 	tx->msg.ifidx = 0;
   1917  1.1      maya 	tx->flags = BWFM_MSGBUF_PKT_FLAGS_FRAME_802_3;
   1918  1.1      maya 	tx->flags |= ac << BWFM_MSGBUF_PKT_FLAGS_PRIO_SHIFT;
   1919  1.1      maya 	tx->seg_cnt = 1;
   1920  1.2  riastrad 	memcpy(tx->txhdr, mtod(*mp, char *), ETHER_HDR_LEN);
   1921  1.1      maya 
   1922  1.2  riastrad 	ret = bwfm_pci_pktid_new(sc, &sc->sc_tx_pkts, mp, &pktid, &paddr);
   1923  1.1      maya 	if (ret) {
   1924  1.1      maya 		if (ret == ENOBUFS) {
   1925  1.1      maya 			printf("%s: no pktid available for TX\n",
   1926  1.1      maya 			    DEVNAME(sc));
   1927  1.1      maya 			sc->sc_tx_pkts_full = 1;
   1928  1.1      maya 		}
   1929  1.1      maya 		bwfm_pci_ring_write_cancel(sc, ring, 1);
   1930  1.1      maya 		return ret;
   1931  1.1      maya 	}
   1932  1.1      maya 	paddr += ETHER_HDR_LEN;
   1933  1.1      maya 
   1934  1.1      maya 	tx->msg.request_id = htole32(pktid);
   1935  1.2  riastrad 	tx->data_len = htole16((*mp)->m_len - ETHER_HDR_LEN);
   1936  1.1      maya 	tx->data_buf_addr.high_addr = htole32(paddr >> 32);
   1937  1.1      maya 	tx->data_buf_addr.low_addr = htole32(paddr & 0xffffffff);
   1938  1.1      maya 
   1939  1.1      maya 	bwfm_pci_ring_write_commit(sc, ring);
   1940  1.1      maya 	return 0;
   1941  1.1      maya }
   1942  1.1      maya 
   1943  1.1      maya #ifdef BWFM_DEBUG
   1944  1.1      maya void
   1945  1.1      maya bwfm_pci_debug_console(struct bwfm_pci_softc *sc)
   1946  1.1      maya {
   1947  1.1      maya 	uint32_t newidx = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh,
   1948  1.1      maya 	    sc->sc_console_base_addr + BWFM_CONSOLE_WRITEIDX);
   1949  1.1      maya 
   1950  1.1      maya 	if (newidx != sc->sc_console_readidx)
   1951  1.1      maya 		DPRINTFN(3, ("BWFM CONSOLE: "));
   1952  1.1      maya 	while (newidx != sc->sc_console_readidx) {
   1953  1.1      maya 		uint8_t ch = bus_space_read_1(sc->sc_tcm_iot, sc->sc_tcm_ioh,
   1954  1.1      maya 		    sc->sc_console_buf_addr + sc->sc_console_readidx);
   1955  1.1      maya 		sc->sc_console_readidx++;
   1956  1.1      maya 		if (sc->sc_console_readidx == sc->sc_console_buf_size)
   1957  1.1      maya 			sc->sc_console_readidx = 0;
   1958  1.1      maya 		if (ch == '\r')
   1959  1.1      maya 			continue;
   1960  1.1      maya 		DPRINTFN(3, ("%c", ch));
   1961  1.1      maya 	}
   1962  1.1      maya }
   1963  1.1      maya #endif
   1964  1.1      maya 
   1965  1.1      maya int
   1966  1.1      maya bwfm_pci_intr(void *v)
   1967  1.1      maya {
   1968  1.1      maya 	struct bwfm_pci_softc *sc = (void *)v;
   1969  1.1      maya 	uint32_t status;
   1970  1.1      maya 
   1971  1.1      maya 	if ((status = bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh,
   1972  1.1      maya 	    BWFM_PCI_PCIE2REG_MAILBOXINT)) == 0)
   1973  1.1      maya 		return 0;
   1974  1.1      maya 
   1975  1.1      maya 	bwfm_pci_intr_disable(sc);
   1976  1.1      maya 	bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
   1977  1.1      maya 	    BWFM_PCI_PCIE2REG_MAILBOXINT, status);
   1978  1.1      maya 
   1979  1.1      maya 	if (status & (BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_FN0_0 |
   1980  1.1      maya 	    BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_FN0_1))
   1981  1.1      maya 		printf("%s: handle MB data\n", __func__);
   1982  1.1      maya 
   1983  1.1      maya 	if (status & BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_D2H_DB) {
   1984  1.1      maya 		bwfm_pci_ring_rx(sc, &sc->sc_rx_complete);
   1985  1.1      maya 		bwfm_pci_ring_rx(sc, &sc->sc_tx_complete);
   1986  1.1      maya 		bwfm_pci_ring_rx(sc, &sc->sc_ctrl_complete);
   1987  1.1      maya 	}
   1988  1.1      maya 
   1989  1.1      maya #ifdef BWFM_DEBUG
   1990  1.1      maya 	bwfm_pci_debug_console(sc);
   1991  1.1      maya #endif
   1992  1.1      maya 
   1993  1.1      maya 	bwfm_pci_intr_enable(sc);
   1994  1.1      maya 	return 1;
   1995  1.1      maya }
   1996  1.1      maya 
   1997  1.1      maya void
   1998  1.1      maya bwfm_pci_intr_enable(struct bwfm_pci_softc *sc)
   1999  1.1      maya {
   2000  1.1      maya 	bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
   2001  1.1      maya 	    BWFM_PCI_PCIE2REG_MAILBOXMASK,
   2002  1.1      maya 	    BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_FN0_0 |
   2003  1.1      maya 	    BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_FN0_1 |
   2004  1.1      maya 	    BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_D2H_DB);
   2005  1.1      maya }
   2006  1.1      maya 
   2007  1.1      maya void
   2008  1.1      maya bwfm_pci_intr_disable(struct bwfm_pci_softc *sc)
   2009  1.1      maya {
   2010  1.1      maya 	bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh,
   2011  1.1      maya 	    BWFM_PCI_PCIE2REG_MAILBOXMASK, 0);
   2012  1.1      maya }
   2013  1.1      maya 
   2014  1.1      maya /* Msgbuf protocol implementation */
   2015  1.1      maya int
   2016  1.1      maya bwfm_pci_msgbuf_query_dcmd(struct bwfm_softc *bwfm, int ifidx,
   2017  1.1      maya     int cmd, char *buf, size_t *len)
   2018  1.1      maya {
   2019  1.1      maya 	struct bwfm_pci_softc *sc = (void *)bwfm;
   2020  1.1      maya 	struct msgbuf_ioctl_req_hdr *req;
   2021  1.1      maya 	struct mbuf *m;
   2022  1.1      maya 	size_t buflen;
   2023  1.1      maya 	int s;
   2024  1.1      maya 
   2025  1.1      maya 	s = splnet();
   2026  1.1      maya 	sc->sc_ioctl_resp_pktid = -1;
   2027  1.1      maya 	req = bwfm_pci_ring_write_reserve(sc, &sc->sc_ctrl_submit);
   2028  1.1      maya 	if (req == NULL) {
   2029  1.1      maya 		printf("%s: cannot reserve for write\n", DEVNAME(sc));
   2030  1.1      maya 		splx(s);
   2031  1.1      maya 		return 1;
   2032  1.1      maya 	}
   2033  1.1      maya 	req->msg.msgtype = MSGBUF_TYPE_IOCTLPTR_REQ;
   2034  1.1      maya 	req->msg.ifidx = 0;
   2035  1.1      maya 	req->msg.flags = 0;
   2036  1.1      maya 	req->msg.request_id = htole32(MSGBUF_IOCTL_REQ_PKTID);
   2037  1.1      maya 	req->cmd = htole32(cmd);
   2038  1.1      maya 	req->output_buf_len = htole16(*len);
   2039  1.1      maya 	req->trans_id = htole16(sc->sc_ioctl_reqid++);
   2040  1.1      maya 
   2041  1.3  riastrad 	buflen = uimin(*len, BWFM_DMA_H2D_IOCTL_BUF_LEN);
   2042  1.1      maya 	req->input_buf_len = htole16(buflen);
   2043  1.1      maya 	req->req_buf_addr.high_addr =
   2044  1.1      maya 	    htole32((uint64_t)BWFM_PCI_DMA_DVA(sc->sc_ioctl_buf) >> 32);
   2045  1.1      maya 	req->req_buf_addr.low_addr =
   2046  1.1      maya 	    htole32((uint64_t)BWFM_PCI_DMA_DVA(sc->sc_ioctl_buf) & 0xffffffff);
   2047  1.1      maya 	if (buf)
   2048  1.1      maya 		memcpy(BWFM_PCI_DMA_KVA(sc->sc_ioctl_buf), buf, buflen);
   2049  1.1      maya 	else
   2050  1.1      maya 		memset(BWFM_PCI_DMA_KVA(sc->sc_ioctl_buf), 0, buflen);
   2051  1.1      maya 
   2052  1.1      maya 	bwfm_pci_ring_write_commit(sc, &sc->sc_ctrl_submit);
   2053  1.1      maya 	splx(s);
   2054  1.1      maya 
   2055  1.1      maya 	if (tsleep(&sc->sc_ioctl_buf, PCATCH, "bwfm", hz)) {
   2056  1.1      maya 		printf("%s: timeout waiting for ioctl response\n",
   2057  1.1      maya 		    DEVNAME(sc));
   2058  1.1      maya 		return 1;
   2059  1.1      maya 	}
   2060  1.1      maya 
   2061  1.1      maya 	m = bwfm_pci_pktid_free(sc, &sc->sc_rx_pkts, sc->sc_ioctl_resp_pktid);
   2062  1.1      maya 	if (m == NULL)
   2063  1.1      maya 		return 1;
   2064  1.1      maya 
   2065  1.3  riastrad 	*len = uimin(buflen, sc->sc_ioctl_resp_ret_len);
   2066  1.1      maya 	if (buf)
   2067  1.1      maya 		memcpy(buf, mtod(m, char *), *len);
   2068  1.1      maya 	m_freem(m);
   2069  1.1      maya 	splx(s);
   2070  1.1      maya 
   2071  1.1      maya 	return 0;
   2072  1.1      maya }
   2073  1.1      maya 
   2074  1.1      maya int
   2075  1.1      maya bwfm_pci_msgbuf_set_dcmd(struct bwfm_softc *bwfm, int ifidx,
   2076  1.1      maya     int cmd, char *buf, size_t len)
   2077  1.1      maya {
   2078  1.1      maya 	return bwfm_pci_msgbuf_query_dcmd(bwfm, ifidx, cmd, buf, &len);
   2079  1.1      maya }
   2080