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