LCOV - code coverage report
Current view: top level - dev/ic - malo.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 1027 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 49 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: malo.c,v 1.117 2018/01/03 23:11:06 dlg Exp $ */
       2             : 
       3             : /*
       4             :  * Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org>
       5             :  * Copyright (c) 2006 Marcus Glocker <mglocker@openbsd.org>
       6             :  *
       7             :  * Permission to use, copy, modify, and distribute this software for any
       8             :  * purpose with or without fee is hereby granted, provided that the above
       9             :  * copyright notice and this permission notice appear in all copies.
      10             :  *
      11             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      12             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      13             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      14             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      15             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      16             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      17             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      18             :  */
      19             : 
      20             : #include "bpfilter.h"
      21             : 
      22             : #include <sys/param.h>
      23             : 
      24             : #include <sys/device.h>
      25             : #include <sys/kernel.h>
      26             : #include <sys/malloc.h>
      27             : #include <sys/mbuf.h>
      28             : #include <sys/socket.h>
      29             : #include <sys/sockio.h>
      30             : #include <sys/systm.h>
      31             : #include <sys/endian.h>
      32             : 
      33             : #include <machine/bus.h>
      34             : #include <machine/intr.h>
      35             : 
      36             : #include <net/if.h>
      37             : #include <net/if_media.h>
      38             : 
      39             : #if NBPFILTER > 0
      40             : #include <net/bpf.h>
      41             : #endif
      42             : 
      43             : #include <netinet/in.h>
      44             : #include <netinet/if_ether.h>
      45             : 
      46             : #include <net80211/ieee80211_var.h>
      47             : #include <net80211/ieee80211_radiotap.h>
      48             : 
      49             : #include <dev/ic/malo.h>
      50             : 
      51             : #ifdef MALO_DEBUG
      52             : int malo_d = 1;
      53             : #define DPRINTF(l, x...)        do { if ((l) <= malo_d) printf(x); } while (0)
      54             : #else
      55             : #define DPRINTF(l, x...)
      56             : #endif
      57             : 
      58             : /* internal structures and defines */
      59             : struct malo_node {
      60             :         struct ieee80211_node           ni;
      61             : };
      62             : 
      63             : struct malo_rx_data {
      64             :         bus_dmamap_t    map;
      65             :         struct mbuf     *m;
      66             : };
      67             : 
      68             : struct malo_tx_data {
      69             :         bus_dmamap_t            map;
      70             :         struct mbuf             *m;
      71             :         uint32_t                softstat;
      72             :         struct ieee80211_node   *ni;
      73             : };
      74             : 
      75             : /* RX descriptor used by HW */
      76             : struct malo_rx_desc {
      77             :         uint8_t         rxctrl;
      78             :         uint8_t         rssi;
      79             :         uint8_t         status;
      80             :         uint8_t         channel;
      81             :         uint16_t        len;
      82             :         uint8_t         reserved1;      /* actually unused */
      83             :         uint8_t         datarate;
      84             :         uint32_t        physdata;       /* DMA address of data */
      85             :         uint32_t        physnext;       /* DMA address of next control block */
      86             :         uint16_t        qosctrl;
      87             :         uint16_t        reserved2;
      88             : } __packed;
      89             : 
      90             : /* TX descriptor used by HW */
      91             : struct malo_tx_desc {
      92             :         uint32_t        status;
      93             :         uint8_t         datarate;
      94             :         uint8_t         txpriority;
      95             :         uint16_t        qosctrl;
      96             :         uint32_t        physdata;       /* DMA address of data */
      97             :         uint16_t        len;
      98             :         uint8_t         destaddr[6];
      99             :         uint32_t        physnext;       /* DMA address of next control block */
     100             :         uint32_t        reserved1;      /* SAP packet info ??? */
     101             :         uint32_t        reserved2;
     102             : } __packed;
     103             : 
     104             : #define MALO_RX_RING_COUNT      256
     105             : #define MALO_TX_RING_COUNT      256
     106             : #define MALO_MAX_SCATTER        8       /* XXX unknown, wild guess */
     107             : #define MALO_CMD_TIMEOUT        50      /* MALO_CMD_TIMEOUT * 100us */
     108             : 
     109             : /*
     110             :  * Firmware commands
     111             :  */
     112             : #define MALO_CMD_GET_HW_SPEC            0x0003
     113             : #define MALO_CMD_SET_RADIO              0x001c
     114             : #define MALO_CMD_SET_AID                0x010d
     115             : #define MALO_CMD_SET_TXPOWER            0x001e
     116             : #define MALO_CMD_SET_ANTENNA            0x0020
     117             : #define MALO_CMD_SET_PRESCAN            0x0107
     118             : #define MALO_CMD_SET_POSTSCAN           0x0108
     119             : #define MALO_CMD_SET_RATE               0x0110
     120             : #define MALO_CMD_SET_CHANNEL            0x010a
     121             : #define MALO_CMD_SET_RTS                0x0113
     122             : #define MALO_CMD_SET_SLOT               0x0114
     123             : #define MALO_CMD_RESPONSE               0x8000
     124             : 
     125             : #define MALO_CMD_RESULT_OK              0x0000  /* everything is fine */
     126             : #define MALO_CMD_RESULT_ERROR           0x0001  /* general error */
     127             : #define MALO_CMD_RESULT_NOSUPPORT       0x0002  /* command not valid */
     128             : #define MALO_CMD_RESULT_PENDING         0x0003  /* will be processed */
     129             : #define MALO_CMD_RESULT_BUSY            0x0004  /* command ignored */
     130             : #define MALO_CMD_RESULT_PARTIALDATA     0x0005  /* buffer too small */
     131             : 
     132             : struct malo_cmdheader {
     133             :         uint16_t        cmd;
     134             :         uint16_t        size;           /* size of the command, incl. header */
     135             :         uint16_t        seqnum;         /* seems not to matter that much */
     136             :         uint16_t        result;         /* set to 0 on request */
     137             :         /* following the data payload, up to 256 bytes */
     138             : };
     139             : 
     140             : struct malo_hw_spec {
     141             :         uint16_t        HwVersion;
     142             :         uint16_t        NumOfWCB;
     143             :         uint16_t        NumOfMCastAdr;
     144             :         uint8_t         PermanentAddress[6];
     145             :         uint16_t        RegionCode;
     146             :         uint16_t        NumberOfAntenna;
     147             :         uint32_t        FWReleaseNumber;
     148             :         uint32_t        WcbBase0;
     149             :         uint32_t        RxPdWrPtr;
     150             :         uint32_t        RxPdRdPtr;
     151             :         uint32_t        CookiePtr;
     152             :         uint32_t        WcbBase1;
     153             :         uint32_t        WcbBase2;
     154             :         uint32_t        WcbBase3;
     155             : } __packed;
     156             : 
     157             : struct malo_cmd_radio {
     158             :         uint16_t        action;
     159             :         uint16_t        preamble_mode;
     160             :         uint16_t        enable;
     161             : } __packed;
     162             : 
     163             : struct malo_cmd_aid {
     164             :         uint16_t        associd;
     165             :         uint8_t         macaddr[6];
     166             :         uint32_t        gprotection;
     167             :         uint8_t         aprates[14];
     168             : } __packed;
     169             : 
     170             : struct malo_cmd_txpower {
     171             :         uint16_t        action;
     172             :         uint16_t        supportpowerlvl;
     173             :         uint16_t        currentpowerlvl;
     174             :         uint16_t        reserved;
     175             :         uint16_t        powerlvllist[8];
     176             : } __packed;
     177             : 
     178             : struct malo_cmd_antenna {
     179             :         uint16_t        action;
     180             :         uint16_t        mode;
     181             : } __packed;
     182             : 
     183             : struct malo_cmd_postscan {
     184             :         uint32_t        isibss;
     185             :         uint8_t         bssid[6];
     186             : } __packed;
     187             : 
     188             : struct malo_cmd_channel {
     189             :         uint16_t        action;
     190             :         uint8_t         channel;
     191             : } __packed;
     192             : 
     193             : struct malo_cmd_rate {
     194             :         uint8_t         dataratetype;
     195             :         uint8_t         rateindex;
     196             :         uint8_t         aprates[14];
     197             : } __packed;
     198             : 
     199             : struct malo_cmd_rts {
     200             :         uint16_t        action;
     201             :         uint32_t        threshold;
     202             : } __packed;
     203             : 
     204             : struct malo_cmd_slot {
     205             :         uint16_t        action;
     206             :         uint8_t         slot;
     207             : } __packed;
     208             : 
     209             : #define malo_mem_write4(sc, off, x) \
     210             :         bus_space_write_4((sc)->sc_mem1_bt, (sc)->sc_mem1_bh, (off), (x))
     211             : #define malo_mem_write2(sc, off, x) \
     212             :         bus_space_write_2((sc)->sc_mem1_bt, (sc)->sc_mem1_bh, (off), (x))
     213             : #define malo_mem_write1(sc, off, x) \
     214             :         bus_space_write_1((sc)->sc_mem1_bt, (sc)->sc_mem1_bh, (off), (x))
     215             : 
     216             : #define malo_mem_read4(sc, off) \
     217             :         bus_space_read_4((sc)->sc_mem1_bt, (sc)->sc_mem1_bh, (off))
     218             : #define malo_mem_read1(sc, off) \
     219             :         bus_space_read_1((sc)->sc_mem1_bt, (sc)->sc_mem1_bh, (off))
     220             : 
     221             : #define malo_ctl_write4(sc, off, x) \
     222             :         bus_space_write_4((sc)->sc_mem2_bt, (sc)->sc_mem2_bh, (off), (x))
     223             : #define malo_ctl_read4(sc, off) \
     224             :         bus_space_read_4((sc)->sc_mem2_bt, (sc)->sc_mem2_bh, (off))
     225             : #define malo_ctl_read1(sc, off) \
     226             :         bus_space_read_1((sc)->sc_mem2_bt, (sc)->sc_mem2_bh, (off))
     227             : 
     228             : #define malo_ctl_barrier(sc, t) \
     229             :         bus_space_barrier((sc)->sc_mem2_bt, (sc)->sc_mem2_bh, 0x0c00, 0xff, (t))
     230             : 
     231             : struct cfdriver malo_cd = {
     232             :         NULL, "malo", DV_IFNET
     233             : };
     234             : 
     235             : int     malo_alloc_cmd(struct malo_softc *sc);
     236             : void    malo_free_cmd(struct malo_softc *sc);
     237             : void    malo_send_cmd(struct malo_softc *sc, bus_addr_t addr);
     238             : int     malo_send_cmd_dma(struct malo_softc *sc, bus_addr_t addr);
     239             : int     malo_alloc_rx_ring(struct malo_softc *sc, struct malo_rx_ring *ring,
     240             :             int count);
     241             : void    malo_reset_rx_ring(struct malo_softc *sc, struct malo_rx_ring *ring);
     242             : void    malo_free_rx_ring(struct malo_softc *sc, struct malo_rx_ring *ring);
     243             : int     malo_alloc_tx_ring(struct malo_softc *sc, struct malo_tx_ring *ring,
     244             :             int count);
     245             : void    malo_reset_tx_ring(struct malo_softc *sc, struct malo_tx_ring *ring);
     246             : void    malo_free_tx_ring(struct malo_softc *sc, struct malo_tx_ring *ring);
     247             : int     malo_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
     248             : void    malo_start(struct ifnet *ifp);
     249             : void    malo_watchdog(struct ifnet *ifp);
     250             : int     malo_newstate(struct ieee80211com *ic, enum ieee80211_state nstate,
     251             :             int arg);
     252             : void    malo_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni,
     253             :             int isnew);
     254             : struct ieee80211_node *
     255             :         malo_node_alloc(struct ieee80211com *ic);
     256             : int     malo_media_change(struct ifnet *ifp);
     257             : void    malo_media_status(struct ifnet *ifp, struct ifmediareq *imr);
     258             : int     malo_chip2rate(int chip_rate);
     259             : int     malo_fix2rate(int fix_rate);
     260             : void    malo_next_scan(void *arg);
     261             : void    malo_tx_intr(struct malo_softc *sc);
     262             : int     malo_tx_mgt(struct malo_softc *sc, struct mbuf *m0,
     263             :             struct ieee80211_node *ni);
     264             : int     malo_tx_data(struct malo_softc *sc, struct mbuf *m0,
     265             :             struct ieee80211_node *ni);
     266             : void    malo_tx_setup_desc(struct malo_softc *sc, struct malo_tx_desc *desc,
     267             :             int len, int rate, const bus_dma_segment_t *segs, int nsegs);
     268             : void    malo_rx_intr(struct malo_softc *sc);
     269             : int     malo_load_bootimg(struct malo_softc *sc);
     270             : int     malo_load_firmware(struct malo_softc *sc);
     271             : 
     272             : int     malo_set_slot(struct malo_softc *sc);
     273             : void    malo_update_slot(struct ieee80211com *ic);
     274             : #ifdef MALO_DEBUG
     275             : void    malo_hexdump(void *buf, int len);
     276             : #endif
     277             : static char *
     278             :         malo_cmd_string(uint16_t cmd);
     279             : static char *
     280             :         malo_cmd_string_result(uint16_t result);
     281             : int     malo_cmd_get_spec(struct malo_softc *sc);
     282             : int     malo_cmd_set_prescan(struct malo_softc *sc);
     283             : int     malo_cmd_set_postscan(struct malo_softc *sc, uint8_t *macaddr,
     284             :             uint8_t ibsson);
     285             : int     malo_cmd_set_channel(struct malo_softc *sc, uint8_t channel);
     286             : int     malo_cmd_set_antenna(struct malo_softc *sc, uint16_t antenna_type);
     287             : int     malo_cmd_set_radio(struct malo_softc *sc, uint16_t mode,
     288             :             uint16_t preamble);
     289             : int     malo_cmd_set_aid(struct malo_softc *sc, uint8_t *bssid,
     290             :             uint16_t associd);
     291             : int     malo_cmd_set_txpower(struct malo_softc *sc, unsigned int powerlevel);
     292             : int     malo_cmd_set_rts(struct malo_softc *sc, uint32_t threshold);
     293             : int     malo_cmd_set_slot(struct malo_softc *sc, uint8_t slot);
     294             : int     malo_cmd_set_rate(struct malo_softc *sc, uint8_t rate);
     295             : void    malo_cmd_response(struct malo_softc *sc);
     296             : 
     297             : int
     298           0 : malo_intr(void *arg)
     299             : {
     300           0 :         struct malo_softc *sc = arg;
     301             :         uint32_t status;
     302             : 
     303           0 :         status = malo_ctl_read4(sc, 0x0c30);
     304           0 :         if (status == 0xffffffff || status == 0)
     305             :                 /* not for us */
     306           0 :                 return (0);
     307             : 
     308           0 :         if (status & 0x1)
     309           0 :                 malo_tx_intr(sc);
     310           0 :         if (status & 0x2)
     311           0 :                 malo_rx_intr(sc);
     312           0 :         if (status & 0x4) {
     313             :                 /* XXX cmd done interrupt handling doesn't work yet */
     314             :                 DPRINTF(1, "%s: got cmd done interrupt\n", sc->sc_dev.dv_xname);
     315             :                 //malo_cmd_response(sc);
     316             :         }
     317             : 
     318           0 :         if (status & ~0x7)
     319             :                 DPRINTF(1, "%s: unknown interrupt %x\n",
     320             :                     sc->sc_dev.dv_xname, status);
     321             : 
     322             :         /* just ack the interrupt */
     323           0 :         malo_ctl_write4(sc, 0x0c30, 0);
     324             : 
     325           0 :         return (1);
     326           0 : }
     327             : 
     328             : int
     329           0 : malo_attach(struct malo_softc *sc)
     330             : {
     331           0 :         struct ieee80211com *ic = &sc->sc_ic;
     332           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
     333             :         int i;
     334             : 
     335             :         /* initialize channel scanning timer */
     336           0 :         timeout_set(&sc->sc_scan_to, malo_next_scan, sc);
     337             : 
     338             :         /* allocate DMA structures */
     339           0 :         malo_alloc_cmd(sc);
     340           0 :         malo_alloc_rx_ring(sc, &sc->sc_rxring, MALO_RX_RING_COUNT);
     341           0 :         malo_alloc_tx_ring(sc, &sc->sc_txring, MALO_TX_RING_COUNT);
     342             : 
     343             :         /* setup interface */
     344           0 :         ifp->if_softc = sc;
     345           0 :         ifp->if_ioctl = malo_ioctl;
     346           0 :         ifp->if_start = malo_start;
     347           0 :         ifp->if_watchdog = malo_watchdog;
     348           0 :         ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
     349           0 :         strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
     350           0 :         IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
     351             : 
     352             :         /* set supported rates */
     353           0 :         ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
     354           0 :         ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
     355           0 :         sc->sc_last_txrate = -1;
     356             : 
     357             :         /* set channels */
     358           0 :         for (i = 1; i <= 14; i++) {
     359           0 :                 ic->ic_channels[i].ic_freq =
     360           0 :                     ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
     361           0 :                 ic->ic_channels[i].ic_flags =
     362             :                     IEEE80211_CHAN_PUREG |
     363             :                     IEEE80211_CHAN_B |
     364             :                     IEEE80211_CHAN_G;
     365             :         }
     366             : 
     367             :         /* set the rest */
     368           0 :         ic->ic_caps =
     369             :             IEEE80211_C_IBSS |
     370             :             IEEE80211_C_MONITOR |
     371             :             IEEE80211_C_SHPREAMBLE |
     372             :             IEEE80211_C_SHSLOT |
     373             :             IEEE80211_C_WEP |
     374             :             IEEE80211_C_RSN;
     375           0 :         ic->ic_opmode = IEEE80211_M_STA;
     376           0 :         ic->ic_state = IEEE80211_S_INIT;
     377           0 :         ic->ic_max_rssi = 75;
     378           0 :         for (i = 0; i < 6; i++)
     379           0 :                 ic->ic_myaddr[i] = malo_ctl_read1(sc, 0xa528 + i);
     380             : 
     381             :         /* show our mac address */
     382           0 :         printf(", address %s\n", ether_sprintf(ic->ic_myaddr));
     383             : 
     384             :         /* attach interface */
     385           0 :         if_attach(ifp);
     386           0 :         ieee80211_ifattach(ifp);
     387             : 
     388             :         /* post attach vector functions */
     389           0 :         sc->sc_newstate = ic->ic_newstate;
     390           0 :         ic->ic_newstate = malo_newstate;
     391           0 :         ic->ic_newassoc = malo_newassoc;
     392           0 :         ic->ic_node_alloc = malo_node_alloc;
     393           0 :         ic->ic_updateslot = malo_update_slot;
     394             : 
     395           0 :         ieee80211_media_init(ifp, malo_media_change, malo_media_status);
     396             : 
     397             : #if NBPFILTER > 0
     398           0 :         bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO,
     399             :             sizeof(struct ieee80211_frame) + 64);
     400             : 
     401           0 :         sc->sc_rxtap_len = sizeof(sc->sc_rxtapu);
     402           0 :         sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
     403           0 :         sc->sc_rxtap.wr_ihdr.it_present = htole32(MALO_RX_RADIOTAP_PRESENT);
     404             : 
     405           0 :         sc->sc_txtap_len = sizeof(sc->sc_txtapu);
     406           0 :         sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
     407           0 :         sc->sc_txtap.wt_ihdr.it_present = htole32(MALO_TX_RADIOTAP_PRESENT);
     408             : #endif
     409             : 
     410           0 :         return (0);
     411             : }
     412             : 
     413             : int
     414           0 : malo_detach(void *arg)
     415             : {
     416           0 :         struct malo_softc *sc = arg;
     417           0 :         struct ieee80211com *ic = &sc->sc_ic;
     418           0 :         struct ifnet *ifp = &ic->ic_if;
     419             : 
     420             :         /* remove channel scanning timer */
     421           0 :         timeout_del(&sc->sc_scan_to);
     422             : 
     423           0 :         malo_stop(sc);
     424           0 :         ieee80211_ifdetach(ifp);
     425           0 :         if_detach(ifp);
     426           0 :         malo_free_cmd(sc);
     427           0 :         malo_free_rx_ring(sc, &sc->sc_rxring);
     428           0 :         malo_free_tx_ring(sc, &sc->sc_txring);
     429             : 
     430           0 :         return (0);
     431             : }
     432             : 
     433             : int
     434           0 : malo_alloc_cmd(struct malo_softc *sc)
     435             : {
     436           0 :         int error, nsegs;
     437             : 
     438           0 :         error = bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, 1,
     439             :             PAGE_SIZE, 0, BUS_DMA_ALLOCNOW, &sc->sc_cmd_dmam);
     440           0 :         if (error != 0) {
     441           0 :                 printf("%s: can not create DMA tag\n", sc->sc_dev.dv_xname);
     442           0 :                 return (-1);
     443             :         }
     444             : 
     445           0 :         error = bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE, PAGE_SIZE,
     446             :             0, &sc->sc_cmd_dmas, 1, &nsegs, BUS_DMA_WAITOK);
     447           0 :         if (error != 0) {
     448           0 :                 printf("%s: error alloc dma memory\n", sc->sc_dev.dv_xname);
     449           0 :                 return (-1);
     450             :         }
     451             : 
     452           0 :         error = bus_dmamem_map(sc->sc_dmat, &sc->sc_cmd_dmas, nsegs,
     453             :             PAGE_SIZE, (caddr_t *)&sc->sc_cmd_mem, BUS_DMA_WAITOK);
     454           0 :         if (error != 0) {
     455           0 :                 printf("%s: error map dma memory\n", sc->sc_dev.dv_xname);
     456           0 :                 return (-1);
     457             :         }
     458             : 
     459           0 :         error = bus_dmamap_load(sc->sc_dmat, sc->sc_cmd_dmam,
     460             :             sc->sc_cmd_mem, PAGE_SIZE, NULL, BUS_DMA_NOWAIT);
     461           0 :         if (error != 0) {
     462           0 :                 printf("%s: error load dma memory\n", sc->sc_dev.dv_xname);
     463           0 :                 bus_dmamem_free(sc->sc_dmat, &sc->sc_cmd_dmas, nsegs);
     464           0 :                 return (-1);
     465             :         }
     466             : 
     467           0 :         sc->sc_cookie = sc->sc_cmd_mem;
     468           0 :         *sc->sc_cookie = htole32(0xaa55aa55);
     469           0 :         sc->sc_cmd_mem = (caddr_t)sc->sc_cmd_mem + sizeof(uint32_t);
     470           0 :         sc->sc_cookie_dmaaddr = sc->sc_cmd_dmam->dm_segs[0].ds_addr;
     471           0 :         sc->sc_cmd_dmaaddr = sc->sc_cmd_dmam->dm_segs[0].ds_addr +
     472             :             sizeof(uint32_t);
     473             : 
     474           0 :         return (0);
     475           0 : }
     476             : 
     477             : void
     478           0 : malo_free_cmd(struct malo_softc *sc)
     479             : {
     480           0 :         bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
     481             :             BUS_DMASYNC_POSTWRITE);
     482           0 :         bus_dmamap_unload(sc->sc_dmat, sc->sc_cmd_dmam);
     483           0 :         bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_cookie, PAGE_SIZE);
     484           0 :         bus_dmamem_free(sc->sc_dmat, &sc->sc_cmd_dmas, 1);
     485           0 : }
     486             : 
     487             : void
     488           0 : malo_send_cmd(struct malo_softc *sc, bus_addr_t addr)
     489             : {
     490           0 :         malo_ctl_write4(sc, 0x0c10, (uint32_t)addr);
     491           0 :         malo_ctl_barrier(sc, BUS_SPACE_BARRIER_WRITE);
     492           0 :         malo_ctl_write4(sc, 0x0c18, 2); /* CPU_TRANSFER_CMD */
     493           0 :         malo_ctl_barrier(sc, BUS_SPACE_BARRIER_WRITE);
     494           0 : }
     495             : 
     496             : int
     497           0 : malo_send_cmd_dma(struct malo_softc *sc, bus_addr_t addr)
     498             : {
     499             :         int i;
     500           0 :         struct malo_cmdheader *hdr = sc->sc_cmd_mem;
     501             : 
     502           0 :         malo_ctl_write4(sc, 0x0c10, (uint32_t)addr);
     503           0 :         malo_ctl_barrier(sc, BUS_SPACE_BARRIER_WRITE);
     504           0 :         malo_ctl_write4(sc, 0x0c18, 2); /* CPU_TRANSFER_CMD */
     505           0 :         malo_ctl_barrier(sc, BUS_SPACE_BARRIER_WRITE);
     506             : 
     507           0 :         for (i = 0; i < MALO_CMD_TIMEOUT; i++) {
     508           0 :                 delay(100);
     509           0 :                 bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
     510             :                     BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
     511           0 :                 if (hdr->cmd & htole16(0x8000))
     512             :                         break;
     513             :         }
     514           0 :         if (i == MALO_CMD_TIMEOUT) {
     515           0 :                 printf("%s: timeout while waiting for cmd response!\n",
     516           0 :                     sc->sc_dev.dv_xname);
     517           0 :                 return (ETIMEDOUT);
     518             :         }
     519             : 
     520           0 :         malo_cmd_response(sc);
     521             : 
     522           0 :         return (0);
     523           0 : }
     524             : 
     525             : int
     526           0 : malo_alloc_rx_ring(struct malo_softc *sc, struct malo_rx_ring *ring, int count)
     527             : {
     528             :         struct malo_rx_desc *desc;
     529             :         struct malo_rx_data *data;
     530           0 :         int i, nsegs, error;
     531             : 
     532           0 :         ring->count = count;
     533           0 :         ring->cur = ring->next = 0;
     534             : 
     535           0 :         error = bus_dmamap_create(sc->sc_dmat,
     536             :             count * sizeof(struct malo_rx_desc), 1,
     537             :             count * sizeof(struct malo_rx_desc), 0,
     538             :             BUS_DMA_NOWAIT, &ring->map);
     539           0 :         if (error != 0) {
     540           0 :                 printf("%s: could not create desc DMA map\n",
     541           0 :                     sc->sc_dev.dv_xname);
     542           0 :                 goto fail;
     543             :         }
     544             : 
     545           0 :         error = bus_dmamem_alloc(sc->sc_dmat,
     546             :             count * sizeof(struct malo_rx_desc),
     547             :             PAGE_SIZE, 0, &ring->seg, 1, &nsegs,
     548             :             BUS_DMA_NOWAIT | BUS_DMA_ZERO);
     549           0 :         if (error != 0) {
     550           0 :                 printf("%s: could not allocate DMA memory\n",
     551           0 :                     sc->sc_dev.dv_xname);
     552           0 :                 goto fail;
     553             :         }
     554             : 
     555           0 :         error = bus_dmamem_map(sc->sc_dmat, &ring->seg, nsegs,
     556             :             count * sizeof(struct malo_rx_desc), (caddr_t *)&ring->desc,
     557             :             BUS_DMA_NOWAIT);
     558           0 :         if (error != 0) {
     559           0 :                 printf("%s: can't map desc DMA memory\n",
     560           0 :                     sc->sc_dev.dv_xname);
     561           0 :                 goto fail;
     562             :         }
     563             : 
     564           0 :         error = bus_dmamap_load(sc->sc_dmat, ring->map, ring->desc,
     565             :             count * sizeof(struct malo_rx_desc), NULL, BUS_DMA_NOWAIT);
     566           0 :         if (error != 0) {
     567           0 :                 printf("%s: could not load desc DMA map\n",
     568           0 :                     sc->sc_dev.dv_xname);
     569           0 :                 goto fail;
     570             :         }
     571             : 
     572           0 :         ring->physaddr = ring->map->dm_segs->ds_addr;
     573             : 
     574           0 :         ring->data = mallocarray(count, sizeof (struct malo_rx_data),
     575             :             M_DEVBUF, M_NOWAIT);
     576           0 :         if (ring->data == NULL) {
     577           0 :                 printf("%s: could not allocate soft data\n",
     578           0 :                     sc->sc_dev.dv_xname);
     579             :                 error = ENOMEM;
     580           0 :                 goto fail;
     581             :         }
     582             : 
     583             :         /*
     584             :          * Pre-allocate Rx buffers and populate Rx ring.
     585             :          */
     586           0 :         bzero(ring->data, count * sizeof (struct malo_rx_data));
     587           0 :         for (i = 0; i < count; i++) {
     588           0 :                 desc = &ring->desc[i];
     589           0 :                 data = &ring->data[i];
     590             : 
     591           0 :                 error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES,
     592             :                     0, BUS_DMA_NOWAIT, &data->map);
     593           0 :                 if (error != 0) {
     594           0 :                         printf("%s: could not create DMA map\n",
     595           0 :                             sc->sc_dev.dv_xname);
     596           0 :                         goto fail;
     597             :                 }
     598             : 
     599           0 :                 MGETHDR(data->m, M_DONTWAIT, MT_DATA);
     600           0 :                 if (data->m == NULL) {
     601           0 :                         printf("%s: could not allocate rx mbuf\n",
     602           0 :                             sc->sc_dev.dv_xname);
     603             :                         error = ENOMEM;
     604           0 :                         goto fail;
     605             :                 }
     606             : 
     607           0 :                 MCLGET(data->m, M_DONTWAIT);
     608           0 :                 if (!(data->m->m_flags & M_EXT)) {
     609           0 :                         printf("%s: could not allocate rx mbuf cluster\n",
     610           0 :                             sc->sc_dev.dv_xname);
     611             :                         error = ENOMEM;
     612           0 :                         goto fail;
     613             :                 }
     614             : 
     615           0 :                 error = bus_dmamap_load(sc->sc_dmat, data->map,
     616             :                     mtod(data->m, void *), MCLBYTES, NULL, BUS_DMA_NOWAIT);
     617           0 :                 if (error != 0) {
     618           0 :                         printf("%s: could not load rx buf DMA map",
     619           0 :                             sc->sc_dev.dv_xname);
     620           0 :                         goto fail;
     621             :                 }
     622             : 
     623           0 :                 desc->status = 1;
     624           0 :                 desc->physdata = htole32(data->map->dm_segs->ds_addr);
     625           0 :                 desc->physnext = htole32(ring->physaddr +
     626             :                     (i + 1) % count * sizeof(struct malo_rx_desc));
     627             :         }
     628             : 
     629           0 :         bus_dmamap_sync(sc->sc_dmat, ring->map, 0, ring->map->dm_mapsize,
     630             :             BUS_DMASYNC_PREWRITE);
     631             : 
     632           0 :         return (0);
     633             : 
     634           0 : fail:   malo_free_rx_ring(sc, ring);
     635           0 :         return (error);
     636           0 : }
     637             : 
     638             : void
     639           0 : malo_reset_rx_ring(struct malo_softc *sc, struct malo_rx_ring *ring)
     640             : {
     641             :         int i;
     642             : 
     643           0 :         for (i = 0; i < ring->count; i++)
     644           0 :                 ring->desc[i].status = 0;
     645             : 
     646           0 :         bus_dmamap_sync(sc->sc_dmat, ring->map, 0, ring->map->dm_mapsize,
     647             :             BUS_DMASYNC_PREWRITE);
     648             : 
     649           0 :         ring->cur = ring->next = 0;
     650           0 : }
     651             : 
     652             : void
     653           0 : malo_free_rx_ring(struct malo_softc *sc, struct malo_rx_ring *ring)
     654             : {
     655             :         struct malo_rx_data *data;
     656             :         int i;
     657             : 
     658           0 :         if (ring->desc != NULL) {
     659           0 :                 bus_dmamap_sync(sc->sc_dmat, ring->map, 0,
     660             :                     ring->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
     661           0 :                 bus_dmamap_unload(sc->sc_dmat, ring->map);
     662           0 :                 bus_dmamem_unmap(sc->sc_dmat, (caddr_t)ring->desc,
     663             :                     ring->count * sizeof(struct malo_rx_desc));
     664           0 :                 bus_dmamem_free(sc->sc_dmat, &ring->seg, 1);
     665           0 :         }
     666             : 
     667           0 :         if (ring->data != NULL) {
     668           0 :                 for (i = 0; i < ring->count; i++) {
     669           0 :                         data = &ring->data[i];
     670             : 
     671           0 :                         if (data->m != NULL) {
     672           0 :                                 bus_dmamap_sync(sc->sc_dmat, data->map, 0,
     673             :                                     data->map->dm_mapsize,
     674             :                                     BUS_DMASYNC_POSTREAD);
     675           0 :                                 bus_dmamap_unload(sc->sc_dmat, data->map);
     676           0 :                                 m_freem(data->m);
     677           0 :                         }
     678             : 
     679           0 :                         if (data->map != NULL)
     680           0 :                                 bus_dmamap_destroy(sc->sc_dmat, data->map);
     681             :                 }
     682           0 :                 free(ring->data, M_DEVBUF, 0);
     683           0 :         }
     684           0 : }
     685             : 
     686             : int
     687           0 : malo_alloc_tx_ring(struct malo_softc *sc, struct malo_tx_ring *ring,
     688             :     int count)
     689             : {
     690           0 :         int i, nsegs, error;
     691             : 
     692           0 :         ring->count = count;
     693           0 :         ring->queued = 0;
     694           0 :         ring->cur = ring->next = ring->stat = 0;
     695             : 
     696           0 :         error = bus_dmamap_create(sc->sc_dmat,
     697             :             count * sizeof(struct malo_tx_desc), 1,
     698             :             count * sizeof(struct malo_tx_desc), 0, BUS_DMA_NOWAIT, &ring->map);
     699           0 :         if (error != 0) {
     700           0 :                 printf("%s: could not create desc DMA map\n",
     701           0 :                     sc->sc_dev.dv_xname);
     702           0 :                 goto fail;
     703             :         }
     704             : 
     705           0 :         error = bus_dmamem_alloc(sc->sc_dmat,
     706             :             count * sizeof(struct malo_tx_desc), PAGE_SIZE, 0,
     707             :             &ring->seg, 1, &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO);
     708           0 :         if (error != 0) {
     709           0 :                 printf("%s: could not allocate DMA memory\n",
     710           0 :                     sc->sc_dev.dv_xname);
     711           0 :                 goto fail;
     712             :         }
     713             : 
     714           0 :         error = bus_dmamem_map(sc->sc_dmat, &ring->seg, nsegs,
     715             :             count * sizeof(struct malo_tx_desc), (caddr_t *)&ring->desc,
     716             :             BUS_DMA_NOWAIT);
     717           0 :         if (error != 0) {
     718           0 :                 printf("%s: can't map desc DMA memory\n",
     719           0 :                     sc->sc_dev.dv_xname);
     720           0 :                 goto fail;
     721             :         }
     722             : 
     723           0 :         error = bus_dmamap_load(sc->sc_dmat, ring->map, ring->desc,
     724             :             count * sizeof(struct malo_tx_desc), NULL, BUS_DMA_NOWAIT);
     725           0 :         if (error != 0) {
     726           0 :                 printf("%s: could not load desc DMA map\n",
     727           0 :                     sc->sc_dev.dv_xname);
     728           0 :                 goto fail;
     729             :         }
     730             : 
     731           0 :         ring->physaddr = ring->map->dm_segs->ds_addr;
     732             : 
     733           0 :         ring->data = mallocarray(count, sizeof(struct malo_tx_data),
     734             :             M_DEVBUF, M_NOWAIT);
     735           0 :         if (ring->data == NULL) {
     736           0 :                 printf("%s: could not allocate soft data\n",
     737           0 :                     sc->sc_dev.dv_xname);
     738             :                 error = ENOMEM;
     739           0 :                 goto fail;
     740             :         }
     741             : 
     742           0 :         memset(ring->data, 0, count * sizeof(struct malo_tx_data));
     743           0 :         for (i = 0; i < count; i++) {
     744           0 :                 error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
     745             :                     MALO_MAX_SCATTER, MCLBYTES, 0, BUS_DMA_NOWAIT,
     746             :                     &ring->data[i].map);
     747           0 :                 if (error != 0) {
     748           0 :                         printf("%s: could not create DMA map\n",
     749           0 :                             sc->sc_dev.dv_xname);
     750           0 :                         goto fail;
     751             :                 }
     752           0 :                 ring->desc[i].physnext = htole32(ring->physaddr +
     753             :                     (i + 1) % count * sizeof(struct malo_tx_desc));
     754             :         }
     755             : 
     756           0 :         return (0);
     757             : 
     758           0 : fail:   malo_free_tx_ring(sc, ring);
     759           0 :         return (error);
     760           0 : }
     761             : 
     762             : void
     763           0 : malo_reset_tx_ring(struct malo_softc *sc, struct malo_tx_ring *ring)
     764             : {
     765             :         struct malo_tx_desc *desc;
     766             :         struct malo_tx_data *data;
     767             :         int i;
     768             : 
     769           0 :         for (i = 0; i < ring->count; i++) {
     770           0 :                 desc = &ring->desc[i];
     771           0 :                 data = &ring->data[i];
     772             : 
     773           0 :                 if (data->m != NULL) {
     774           0 :                         bus_dmamap_sync(sc->sc_dmat, data->map, 0,
     775             :                             data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
     776           0 :                         bus_dmamap_unload(sc->sc_dmat, data->map);
     777           0 :                         m_freem(data->m);
     778           0 :                         data->m = NULL;
     779           0 :                 }
     780             : 
     781             :                 /*
     782             :                  * The node has already been freed at that point so don't call
     783             :                  * ieee80211_release_node() here.
     784             :                  */
     785           0 :                 data->ni = NULL;
     786             : 
     787           0 :                 desc->status = 0;
     788             :         }
     789             : 
     790           0 :         bus_dmamap_sync(sc->sc_dmat, ring->map, 0, ring->map->dm_mapsize,
     791             :             BUS_DMASYNC_PREWRITE);
     792             : 
     793           0 :         ring->queued = 0;
     794           0 :         ring->cur = ring->next = ring->stat = 0;
     795           0 : }
     796             : 
     797             : void
     798           0 : malo_free_tx_ring(struct malo_softc *sc, struct malo_tx_ring *ring)
     799             : {
     800             :         struct malo_tx_data *data;
     801             :         int i;
     802             : 
     803           0 :         if (ring->desc != NULL) {
     804           0 :                 bus_dmamap_sync(sc->sc_dmat, ring->map, 0,
     805             :                     ring->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
     806           0 :                 bus_dmamap_unload(sc->sc_dmat, ring->map);
     807           0 :                 bus_dmamem_unmap(sc->sc_dmat, (caddr_t)ring->desc,
     808             :                     ring->count * sizeof(struct malo_tx_desc));
     809           0 :                 bus_dmamem_free(sc->sc_dmat, &ring->seg, 1);
     810           0 :         }
     811             : 
     812           0 :         if (ring->data != NULL) {
     813           0 :                 for (i = 0; i < ring->count; i++) {
     814           0 :                         data = &ring->data[i];
     815             : 
     816           0 :                         if (data->m != NULL) {
     817           0 :                                 bus_dmamap_sync(sc->sc_dmat, data->map, 0,
     818             :                                     data->map->dm_mapsize,
     819             :                                     BUS_DMASYNC_POSTWRITE);
     820           0 :                                 bus_dmamap_unload(sc->sc_dmat, data->map);
     821           0 :                                 m_freem(data->m);
     822           0 :                         }
     823             : 
     824             :                         /*
     825             :                          * The node has already been freed at that point so
     826             :                          * don't call ieee80211_release_node() here.
     827             :                          */
     828           0 :                         data->ni = NULL;
     829             : 
     830           0 :                         if (data->map != NULL)
     831           0 :                                 bus_dmamap_destroy(sc->sc_dmat, data->map);
     832             :                 }
     833           0 :                 free(ring->data, M_DEVBUF, 0);
     834           0 :         }
     835           0 : }
     836             : 
     837             : int
     838           0 : malo_init(struct ifnet *ifp)
     839             : {
     840           0 :         struct malo_softc *sc = ifp->if_softc;
     841           0 :         struct ieee80211com *ic = &sc->sc_ic;
     842             :         uint8_t chan;
     843             :         int error;
     844             : 
     845             :         DPRINTF(1, "%s: %s\n", ifp->if_xname, __func__);
     846             : 
     847             :         /* if interface already runs stop it first */
     848           0 :         if (ifp->if_flags & IFF_RUNNING)
     849           0 :                 malo_stop(sc);
     850             : 
     851             :         /* power on cardbus socket */
     852           0 :         if (sc->sc_enable)
     853           0 :                 sc->sc_enable(sc);
     854             : 
     855             :         /* disable interrupts */
     856           0 :         malo_ctl_read4(sc, 0x0c30);
     857           0 :         malo_ctl_write4(sc, 0x0c30, 0);
     858           0 :         malo_ctl_write4(sc, 0x0c34, 0);
     859           0 :         malo_ctl_write4(sc, 0x0c3c, 0);
     860             : 
     861             :         /* load firmware */
     862           0 :         if ((error = malo_load_bootimg(sc)))
     863             :                 goto fail;
     864           0 :         if ((error = malo_load_firmware(sc)))
     865             :                 goto fail;
     866             : 
     867             :         /* enable interrupts */
     868           0 :         malo_ctl_write4(sc, 0x0c34, 0x1f);
     869           0 :         malo_ctl_barrier(sc, BUS_SPACE_BARRIER_WRITE);
     870           0 :         malo_ctl_write4(sc, 0x0c3c, 0x1f);
     871           0 :         malo_ctl_barrier(sc, BUS_SPACE_BARRIER_WRITE);
     872             : 
     873           0 :         if ((error = malo_cmd_get_spec(sc)))
     874             :                 goto fail;
     875             : 
     876             :         /* select default channel */
     877           0 :         ic->ic_bss->ni_chan = ic->ic_ibss_chan;
     878           0 :         chan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
     879             : 
     880             :         /* initialize hardware */
     881           0 :         if ((error = malo_cmd_set_channel(sc, chan))) {
     882           0 :                 printf("%s: setting channel failed!\n",
     883           0 :                     sc->sc_dev.dv_xname);
     884           0 :                 goto fail;
     885             :         }
     886           0 :         if ((error = malo_cmd_set_antenna(sc, 1))) {
     887           0 :                 printf("%s: setting RX antenna failed!\n",
     888           0 :                     sc->sc_dev.dv_xname);
     889           0 :                 goto fail;
     890             :         }
     891           0 :         if ((error = malo_cmd_set_antenna(sc, 2))) {
     892           0 :                 printf("%s: setting TX antenna failed!\n",
     893           0 :                     sc->sc_dev.dv_xname);
     894           0 :                 goto fail;
     895             :         }
     896           0 :         if ((error = malo_cmd_set_radio(sc, 1, 5))) {
     897           0 :                 printf("%s: turn radio on failed!\n",
     898           0 :                     sc->sc_dev.dv_xname);
     899           0 :                 goto fail;
     900             :         }
     901           0 :         if ((error = malo_cmd_set_txpower(sc, 100))) {
     902           0 :                 printf("%s: setting TX power failed!\n",
     903           0 :                     sc->sc_dev.dv_xname);
     904           0 :                 goto fail;
     905             :         }
     906           0 :         if ((error = malo_cmd_set_rts(sc, IEEE80211_RTS_MAX))) {
     907           0 :                 printf("%s: setting RTS failed!\n",
     908           0 :                     sc->sc_dev.dv_xname);
     909           0 :                 goto fail;
     910             :         }
     911             : 
     912           0 :         ifp->if_flags |= IFF_RUNNING;
     913             : 
     914           0 :         if (ic->ic_opmode != IEEE80211_M_MONITOR)
     915             :                 /* start background scanning */
     916           0 :                 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
     917             :         else
     918             :                 /* in monitor mode change directly into run state */
     919           0 :                 ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
     920             : 
     921           0 :         return (0);
     922             : 
     923             : fail:
     924             :         /* reset adapter */
     925             :         DPRINTF(1, "%s: malo_init failed, resetting card\n",
     926             :             sc->sc_dev.dv_xname);
     927           0 :         malo_stop(sc);
     928           0 :         return (error);
     929           0 : }
     930             : 
     931             : int
     932           0 : malo_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
     933             : {
     934           0 :         struct malo_softc *sc = ifp->if_softc;
     935           0 :         struct ieee80211com *ic = &sc->sc_ic;
     936             :         int s, error = 0;
     937             :         uint8_t chan;
     938             : 
     939           0 :         s = splnet();
     940             : 
     941           0 :         switch (cmd) {
     942             :         case SIOCSIFADDR:
     943           0 :                 ifp->if_flags |= IFF_UP;
     944             :                 /* FALLTHROUGH */
     945             :         case SIOCSIFFLAGS:
     946           0 :                 if (ifp->if_flags & IFF_UP) {
     947           0 :                         if ((ifp->if_flags & IFF_RUNNING) == 0)
     948           0 :                                 malo_init(ifp);
     949             :                 } else {
     950           0 :                         if (ifp->if_flags & IFF_RUNNING)
     951           0 :                                 malo_stop(sc);
     952             :                 }
     953             :                 break;
     954             :         case SIOCS80211CHANNEL:
     955             :                 /* allow fast channel switching in monitor mode */
     956           0 :                 error = ieee80211_ioctl(ifp, cmd, data);
     957           0 :                 if (error == ENETRESET &&
     958           0 :                     ic->ic_opmode == IEEE80211_M_MONITOR) {
     959           0 :                         if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
     960             :                             (IFF_UP | IFF_RUNNING)) {
     961           0 :                                 ic->ic_bss->ni_chan = ic->ic_ibss_chan;
     962           0 :                                 chan = ieee80211_chan2ieee(ic,
     963           0 :                                     ic->ic_bss->ni_chan);
     964           0 :                                 malo_cmd_set_channel(sc, chan);
     965           0 :                         }
     966             :                         error = 0;
     967           0 :                 }
     968             :                 break;
     969             :         default:
     970           0 :                 error = ieee80211_ioctl(ifp, cmd, data);
     971           0 :                 break;
     972             :         }
     973             : 
     974           0 :         if (error == ENETRESET) {
     975           0 :                 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
     976             :                     (IFF_UP | IFF_RUNNING))
     977           0 :                         malo_init(ifp);
     978             :                 error = 0;
     979           0 :         }
     980             : 
     981           0 :         splx(s);
     982             : 
     983           0 :         return (error);
     984             : }
     985             : 
     986             : void
     987           0 : malo_start(struct ifnet *ifp)
     988             : {
     989           0 :         struct malo_softc *sc = ifp->if_softc;
     990           0 :         struct ieee80211com *ic = &sc->sc_ic;
     991             :         struct mbuf *m0;
     992           0 :         struct ieee80211_node *ni;
     993             : 
     994             :         DPRINTF(2, "%s: %s\n", sc->sc_dev.dv_xname, __func__);
     995             : 
     996           0 :         if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd))
     997           0 :                 return;
     998             : 
     999           0 :         for (;;) {
    1000           0 :                 if (sc->sc_txring.queued >= MALO_TX_RING_COUNT - 1) {
    1001           0 :                         ifq_set_oactive(&ifp->if_snd);
    1002           0 :                         break;
    1003             :                 }
    1004             : 
    1005           0 :                 m0 = mq_dequeue(&ic->ic_mgtq);
    1006           0 :                 if (m0 != NULL) {
    1007           0 :                         ni = m0->m_pkthdr.ph_cookie;
    1008             : #if NBPFILTER > 0
    1009           0 :                         if (ic->ic_rawbpf != NULL)
    1010           0 :                                 bpf_mtap(ic->ic_rawbpf, m0, BPF_DIRECTION_OUT);
    1011             : #endif
    1012           0 :                         if (malo_tx_mgt(sc, m0, ni) != 0)
    1013             :                                 break;
    1014             :                 } else {
    1015           0 :                         if (ic->ic_state != IEEE80211_S_RUN)
    1016             :                                 break;
    1017             : 
    1018           0 :                         IFQ_DEQUEUE(&ifp->if_snd, m0);
    1019           0 :                         if (m0 == NULL)
    1020             :                                 break;
    1021             : #if NBPFILTER > 0
    1022           0 :                         if (ifp->if_bpf != NULL)
    1023           0 :                                 bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
    1024             : #endif
    1025           0 :                         m0 = ieee80211_encap(ifp, m0, &ni);
    1026           0 :                         if (m0 == NULL)
    1027           0 :                                 continue;
    1028             : #if NBPFILTER > 0
    1029           0 :                         if (ic->ic_rawbpf != NULL)
    1030           0 :                                 bpf_mtap(ic->ic_rawbpf, m0, BPF_DIRECTION_OUT);
    1031             : #endif
    1032           0 :                         if (malo_tx_data(sc, m0, ni) != 0) {
    1033           0 :                                 if (ni != NULL)
    1034           0 :                                         ieee80211_release_node(ic, ni);
    1035           0 :                                 ifp->if_oerrors++;
    1036           0 :                                 break;
    1037             :                         }
    1038             :                 }
    1039             :         }
    1040           0 : }
    1041             : 
    1042             : void
    1043           0 : malo_stop(struct malo_softc *sc)
    1044             : {
    1045           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1046           0 :         struct ifnet *ifp = &ic->ic_if;
    1047             : 
    1048             :         DPRINTF(1, "%s: %s\n", ifp->if_xname, __func__);
    1049             : 
    1050             :         /* reset adapter */
    1051           0 :         if (ifp->if_flags & IFF_RUNNING)
    1052           0 :                 malo_ctl_write4(sc, 0x0c18, (1 << 15));
    1053             : 
    1054             :         /* device is not running anymore */
    1055           0 :         ifp->if_flags &= ~IFF_RUNNING;
    1056           0 :         ifq_clr_oactive(&ifp->if_snd);
    1057             : 
    1058             :         /* change back to initial state */
    1059           0 :         ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
    1060             : 
    1061             :         /* reset RX / TX rings */
    1062           0 :         malo_reset_tx_ring(sc, &sc->sc_txring);
    1063           0 :         malo_reset_rx_ring(sc, &sc->sc_rxring);
    1064             : 
    1065             :         /* set initial rate */
    1066           0 :         sc->sc_last_txrate = -1;
    1067             : 
    1068             :         /* power off cardbus socket */
    1069           0 :         if (sc->sc_disable)
    1070           0 :                 sc->sc_disable(sc);
    1071           0 : }
    1072             : 
    1073             : void
    1074           0 : malo_watchdog(struct ifnet *ifp)
    1075             : {
    1076             : 
    1077           0 : }
    1078             : 
    1079             : int
    1080           0 : malo_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
    1081             : {
    1082           0 :         struct malo_softc *sc = ic->ic_if.if_softc;
    1083             :         enum ieee80211_state ostate;
    1084             :         uint8_t chan;
    1085             :         int rate;
    1086             : 
    1087             :         DPRINTF(2, "%s: %s\n", sc->sc_dev.dv_xname, __func__);
    1088             : 
    1089           0 :         ostate = ic->ic_state;
    1090           0 :         timeout_del(&sc->sc_scan_to);
    1091             : 
    1092           0 :         switch (nstate) {
    1093             :         case IEEE80211_S_INIT:
    1094             :                 break;
    1095             :         case IEEE80211_S_SCAN:
    1096           0 :                 if (ostate == IEEE80211_S_INIT) {
    1097           0 :                         if (malo_cmd_set_prescan(sc) != 0)
    1098             :                                 DPRINTF(1, "%s: can't set prescan\n",
    1099             :                                     sc->sc_dev.dv_xname);
    1100           0 :                 } else {
    1101           0 :                         chan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
    1102             : 
    1103           0 :                         malo_cmd_set_channel(sc, chan);
    1104             :                 }
    1105           0 :                 timeout_add_msec(&sc->sc_scan_to, 500);
    1106           0 :                 break;
    1107             :         case IEEE80211_S_AUTH:
    1108             :                 DPRINTF(1, "%s: newstate AUTH\n", sc->sc_dev.dv_xname);
    1109           0 :                 malo_cmd_set_postscan(sc, ic->ic_myaddr, 1);
    1110           0 :                 chan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
    1111           0 :                 malo_cmd_set_channel(sc, chan);
    1112           0 :                 break;
    1113             :         case IEEE80211_S_ASSOC:
    1114             :                 DPRINTF(1, "%s: newstate ASSOC\n", sc->sc_dev.dv_xname);
    1115           0 :                 if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
    1116           0 :                         malo_cmd_set_radio(sc, 1, 3); /* short preamble */
    1117             :                 else
    1118           0 :                         malo_cmd_set_radio(sc, 1, 1); /* long preamble */
    1119             : 
    1120           0 :                 malo_cmd_set_aid(sc, ic->ic_bss->ni_bssid,
    1121           0 :                     ic->ic_bss->ni_associd);
    1122             : 
    1123           0 :                 if (ic->ic_fixed_rate == -1)
    1124             :                         /* automatic rate adaption */
    1125           0 :                         malo_cmd_set_rate(sc, 0);
    1126             :                 else {
    1127             :                         /* fixed rate */
    1128           0 :                         rate = malo_fix2rate(ic->ic_fixed_rate);
    1129           0 :                         malo_cmd_set_rate(sc, rate);
    1130             :                 }
    1131             : 
    1132           0 :                 malo_set_slot(sc);
    1133           0 :                 break;
    1134             :         case IEEE80211_S_RUN:
    1135             :                 DPRINTF(1, "%s: newstate RUN\n", sc->sc_dev.dv_xname);
    1136             :                 break;
    1137             :         default:
    1138             :                 break;
    1139             :         }
    1140             : 
    1141           0 :         return (sc->sc_newstate(ic, nstate, arg));
    1142             : }
    1143             : 
    1144             : void
    1145           0 : malo_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew)
    1146             : {
    1147             : 
    1148           0 : }
    1149             : 
    1150             : struct ieee80211_node *
    1151           0 : malo_node_alloc(struct ieee80211com *ic)
    1152             : {
    1153             :         struct malo_node *wn;
    1154             : 
    1155           0 :         wn = malloc(sizeof(*wn), M_DEVBUF, M_NOWAIT | M_ZERO);
    1156           0 :         if (wn == NULL)
    1157           0 :                 return (NULL);
    1158             : 
    1159           0 :         return ((struct ieee80211_node *)wn);
    1160           0 : }
    1161             : 
    1162             : int
    1163           0 : malo_media_change(struct ifnet *ifp)
    1164             : {
    1165             :         int error;
    1166             : 
    1167             :         DPRINTF(1, "%s: %s\n", ifp->if_xname, __func__);
    1168             : 
    1169           0 :         error = ieee80211_media_change(ifp);
    1170           0 :         if (error != ENETRESET)
    1171           0 :                 return (error);
    1172             : 
    1173           0 :         if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
    1174           0 :                 malo_init(ifp);
    1175             : 
    1176           0 :         return (0);
    1177           0 : }
    1178             : 
    1179             : void
    1180           0 : malo_media_status(struct ifnet *ifp, struct ifmediareq *imr)
    1181             : {
    1182           0 :         struct malo_softc *sc = ifp->if_softc;
    1183           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1184             : 
    1185           0 :         imr->ifm_status = IFM_AVALID;
    1186           0 :         imr->ifm_active = IFM_IEEE80211;
    1187           0 :         if (ic->ic_state == IEEE80211_S_RUN)
    1188           0 :                 imr->ifm_status |= IFM_ACTIVE;
    1189             : 
    1190             :         /* report last TX rate used by chip */
    1191           0 :         imr->ifm_active |= ieee80211_rate2media(ic, sc->sc_last_txrate,
    1192           0 :             ic->ic_curmode);
    1193             : 
    1194           0 :         switch (ic->ic_opmode) {
    1195             :         case IEEE80211_M_STA:
    1196             :                 break;
    1197             : #ifndef IEEE80211_STA_ONLY
    1198             :         case IEEE80211_M_IBSS:
    1199           0 :                 imr->ifm_active |= IFM_IEEE80211_ADHOC;
    1200           0 :                 break;
    1201             :         case IEEE80211_M_AHDEMO:
    1202             :                 break;
    1203             :         case IEEE80211_M_HOSTAP:
    1204             :                 break;
    1205             : #endif
    1206             :         case IEEE80211_M_MONITOR:
    1207           0 :                 imr->ifm_active |= IFM_IEEE80211_MONITOR;
    1208           0 :                 break;
    1209             :         default:
    1210             :                 break;
    1211             :         }
    1212             : 
    1213           0 :         switch (ic->ic_curmode) {
    1214             :                 case IEEE80211_MODE_11B:
    1215           0 :                         imr->ifm_active |= IFM_IEEE80211_11B;
    1216           0 :                         break;
    1217             :                 case IEEE80211_MODE_11G:
    1218           0 :                         imr->ifm_active |= IFM_IEEE80211_11G;
    1219           0 :                         break;
    1220             :         }
    1221           0 : }
    1222             : 
    1223             : int
    1224           0 : malo_chip2rate(int chip_rate)
    1225             : {
    1226           0 :         switch (chip_rate) {
    1227             :         /* CCK rates */
    1228           0 :         case  0:        return (2);
    1229           0 :         case  1:        return (4);
    1230           0 :         case  2:        return (11);
    1231           0 :         case  3:        return (22);
    1232             : 
    1233             :         /* OFDM rates */
    1234           0 :         case  4:        return (0); /* reserved */
    1235           0 :         case  5:        return (12);
    1236           0 :         case  6:        return (18);
    1237           0 :         case  7:        return (24);
    1238           0 :         case  8:        return (36);
    1239           0 :         case  9:        return (48);
    1240           0 :         case 10:        return (72);
    1241           0 :         case 11:        return (96);
    1242           0 :         case 12:        return (108);
    1243             : 
    1244             :         /* no rate select yet or unknown rate */
    1245           0 :         default:        return (-1);
    1246             :         }
    1247           0 : }
    1248             : 
    1249             : int
    1250           0 : malo_fix2rate(int fix_rate)
    1251             : {
    1252           0 :         switch (fix_rate) {
    1253             :         /* CCK rates */
    1254           0 :         case  0:        return (2);
    1255           0 :         case  1:        return (4);
    1256           0 :         case  2:        return (11);
    1257           0 :         case  3:        return (22);
    1258             : 
    1259             :         /* OFDM rates */
    1260           0 :         case  4:        return (12);
    1261           0 :         case  5:        return (18);
    1262           0 :         case  6:        return (24);
    1263           0 :         case  7:        return (36);
    1264           0 :         case  8:        return (48);
    1265           0 :         case  9:        return (72);
    1266           0 :         case 10:        return (96);
    1267           0 :         case 11:        return (108);
    1268             : 
    1269             :         /* unknown rate: should not happen */
    1270           0 :         default:        return (0);
    1271             :         }
    1272           0 : }
    1273             : 
    1274             : void
    1275           0 : malo_next_scan(void *arg)
    1276             : {
    1277           0 :         struct malo_softc *sc = arg;
    1278           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1279           0 :         struct ifnet *ifp = &ic->ic_if;
    1280             :         int s;
    1281             : 
    1282             :         DPRINTF(1, "%s: %s\n", ifp->if_xname, __func__);
    1283             : 
    1284           0 :         s = splnet();
    1285             : 
    1286           0 :         if (ic->ic_state == IEEE80211_S_SCAN)
    1287           0 :                 ieee80211_next_scan(ifp);
    1288             : 
    1289           0 :         splx(s);
    1290           0 : }
    1291             : 
    1292             : void
    1293           0 : malo_tx_intr(struct malo_softc *sc)
    1294             : {
    1295           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1296           0 :         struct ifnet *ifp = &ic->ic_if;
    1297             :         struct malo_tx_desc *desc;
    1298             :         struct malo_tx_data *data;
    1299             :         struct malo_node *rn;
    1300             :         int stat;
    1301             : 
    1302             :         DPRINTF(2, "%s: %s\n", sc->sc_dev.dv_xname, __func__);
    1303             : 
    1304           0 :         stat = sc->sc_txring.stat;
    1305           0 :         for (;;) {
    1306           0 :                 desc = &sc->sc_txring.desc[sc->sc_txring.stat];
    1307           0 :                 data = &sc->sc_txring.data[sc->sc_txring.stat];
    1308           0 :                 rn = (struct malo_node *)data->ni;
    1309             : 
    1310             :                 /* check if TX descriptor is not owned by FW anymore */
    1311           0 :                 if ((letoh32(desc->status) & 0x80000000) ||
    1312           0 :                     !(letoh32(data->softstat) & 0x80))
    1313             :                         break;
    1314             : 
    1315             :                 /* if no frame has been sent, ignore */
    1316           0 :                 if (rn == NULL)
    1317             :                         goto next;
    1318             : 
    1319             :                 /* check TX state */
    1320           0 :                 switch (letoh32(desc->status) & 0x1) {
    1321             :                 case 0x1:
    1322             :                         DPRINTF(2, "%s: data frame was sent successfully\n",
    1323             :                             sc->sc_dev.dv_xname);
    1324             :                         break;
    1325             :                 default:
    1326             :                         DPRINTF(1, "%s: data frame sending error\n",
    1327             :                             sc->sc_dev.dv_xname);
    1328           0 :                         ifp->if_oerrors++;
    1329           0 :                         break;
    1330             :                 }
    1331             : 
    1332             :                 /* save last used TX rate */
    1333           0 :                 sc->sc_last_txrate = malo_chip2rate(desc->datarate);
    1334             : 
    1335             :                 /* cleanup TX data and TX descriptor */
    1336           0 :                 bus_dmamap_sync(sc->sc_dmat, data->map, 0,
    1337             :                     data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
    1338           0 :                 bus_dmamap_unload(sc->sc_dmat, data->map);
    1339           0 :                 m_freem(data->m);
    1340           0 :                 ieee80211_release_node(ic, data->ni);
    1341           0 :                 data->m = NULL;
    1342           0 :                 data->ni = NULL;
    1343           0 :                 data->softstat &= htole32(~0x80);
    1344           0 :                 desc->status = 0;
    1345           0 :                 desc->len = 0;
    1346             : 
    1347             :                 DPRINTF(2, "%s: tx done idx=%d\n",
    1348             :                     sc->sc_dev.dv_xname, sc->sc_txring.stat);
    1349             : 
    1350           0 :                 sc->sc_txring.queued--;
    1351             : next:
    1352           0 :                 if (++sc->sc_txring.stat >= sc->sc_txring.count)
    1353           0 :                         sc->sc_txring.stat = 0;
    1354           0 :                 if (sc->sc_txring.stat == stat)
    1355             :                         break;
    1356             :         }
    1357             : 
    1358           0 :         sc->sc_tx_timer = 0;
    1359           0 :         ifq_clr_oactive(&ifp->if_snd);
    1360           0 :         malo_start(ifp);
    1361           0 : }
    1362             : 
    1363             : int
    1364           0 : malo_tx_mgt(struct malo_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
    1365             : {
    1366           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1367           0 :         struct ifnet *ifp = &ic->ic_if;
    1368             :         struct malo_tx_desc *desc;
    1369             :         struct malo_tx_data *data;
    1370             :         struct ieee80211_frame *wh;
    1371             :         int error;
    1372             : 
    1373             :         DPRINTF(2, "%s: %s\n", sc->sc_dev.dv_xname, __func__);
    1374             : 
    1375           0 :         desc = &sc->sc_txring.desc[sc->sc_txring.cur];
    1376           0 :         data = &sc->sc_txring.data[sc->sc_txring.cur];
    1377             : 
    1378           0 :         if (m0->m_len < sizeof(struct ieee80211_frame)) {
    1379           0 :                 m0 = m_pullup(m0, sizeof(struct ieee80211_frame));
    1380           0 :                 if (m0 == NULL) {
    1381           0 :                         ifp->if_ierrors++;
    1382           0 :                         return (ENOBUFS);
    1383             :                 }
    1384             :         }
    1385           0 :         wh = mtod(m0, struct ieee80211_frame *);
    1386             : 
    1387             : #if NBPFILTER > 0
    1388           0 :         if (sc->sc_drvbpf != NULL) {
    1389           0 :                 struct mbuf mb;
    1390           0 :                 struct malo_tx_radiotap_hdr *tap = &sc->sc_txtap;
    1391             : 
    1392           0 :                 tap->wt_flags = 0;
    1393           0 :                 tap->wt_rate = sc->sc_last_txrate;
    1394           0 :                 tap->wt_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq);
    1395           0 :                 tap->wt_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags);
    1396             : 
    1397           0 :                 mb.m_data = (caddr_t)tap;
    1398           0 :                 mb.m_len = sc->sc_txtap_len;
    1399           0 :                 mb.m_next = m0;
    1400           0 :                 mb.m_nextpkt = NULL;
    1401           0 :                 mb.m_type = 0;
    1402           0 :                 mb.m_flags = 0;
    1403           0 :                 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT);
    1404           0 :         }
    1405             : #endif
    1406             :         /*
    1407             :          * inject FW specific fields into the 802.11 frame
    1408             :          *
    1409             :          *  2 bytes FW len (inject)
    1410             :          * 24 bytes 802.11 frame header
    1411             :          *  6 bytes addr4 (inject)
    1412             :          *  n bytes 802.11 frame body
    1413             :          */
    1414           0 :         if (M_LEADINGSPACE(m0) < 8) {
    1415           0 :                 if (M_TRAILINGSPACE(m0) < 8)
    1416           0 :                         panic("%s: not enough space for mbuf dance",
    1417           0 :                             sc->sc_dev.dv_xname);
    1418           0 :                 bcopy(m0->m_data, m0->m_data + 8, m0->m_len);
    1419           0 :                 m0->m_data += 8;
    1420           0 :         }
    1421             : 
    1422             :         /* move frame header */
    1423           0 :         bcopy(m0->m_data, m0->m_data - 6, sizeof(*wh));
    1424           0 :         m0->m_data -= 8;
    1425           0 :         m0->m_len += 8;
    1426           0 :         m0->m_pkthdr.len += 8;
    1427           0 :         *mtod(m0, uint16_t *) = htole16(m0->m_len - 32); /* FW len */
    1428             : 
    1429           0 :         error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m0,
    1430             :             BUS_DMA_NOWAIT);
    1431           0 :         if (error != 0) {
    1432           0 :                 printf("%s: can't map mbuf (error %d)\n",
    1433           0 :                     sc->sc_dev.dv_xname, error);
    1434           0 :                 m_freem(m0);
    1435           0 :                 return (error);
    1436             :         }
    1437             : 
    1438           0 :         data->m = m0;
    1439           0 :         data->ni = ni;
    1440           0 :         data->softstat |= htole32(0x80);
    1441             : 
    1442           0 :         malo_tx_setup_desc(sc, desc, m0->m_pkthdr.len, 0,
    1443           0 :             data->map->dm_segs, data->map->dm_nsegs);
    1444             : 
    1445           0 :         bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,
    1446             :             BUS_DMASYNC_PREWRITE);
    1447           0 :         bus_dmamap_sync(sc->sc_dmat, sc->sc_txring.map,
    1448             :             sc->sc_txring.cur * sizeof(struct malo_tx_desc),
    1449             :             sizeof(struct malo_tx_desc), BUS_DMASYNC_PREWRITE);
    1450             : 
    1451             :         DPRINTF(2, "%s: sending mgmt frame, pktlen=%u, idx=%u\n",
    1452             :             sc->sc_dev.dv_xname, m0->m_pkthdr.len, sc->sc_txring.cur);
    1453             : 
    1454           0 :         sc->sc_txring.queued++;
    1455           0 :         sc->sc_txring.cur = (sc->sc_txring.cur + 1) % MALO_TX_RING_COUNT;
    1456             : 
    1457             :         /* kick mgmt TX */
    1458           0 :         malo_ctl_write4(sc, 0x0c18, 1);
    1459           0 :         malo_ctl_barrier(sc, BUS_SPACE_BARRIER_WRITE);
    1460             : 
    1461           0 :         return (0);
    1462           0 : }
    1463             : 
    1464             : int
    1465           0 : malo_tx_data(struct malo_softc *sc, struct mbuf *m0,
    1466             :     struct ieee80211_node *ni)
    1467             : {
    1468           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1469           0 :         struct ifnet *ifp = &ic->ic_if;
    1470             :         struct malo_tx_desc *desc;
    1471             :         struct malo_tx_data *data;
    1472             :         struct ieee80211_frame *wh;
    1473             :         struct ieee80211_key *k;
    1474             :         struct mbuf *mnew;
    1475             :         int error;
    1476             : 
    1477             :         DPRINTF(2, "%s: %s\n", sc->sc_dev.dv_xname, __func__);
    1478             : 
    1479           0 :         desc = &sc->sc_txring.desc[sc->sc_txring.cur];
    1480           0 :         data = &sc->sc_txring.data[sc->sc_txring.cur];
    1481             : 
    1482           0 :         if (m0->m_len < sizeof(struct ieee80211_frame)) {
    1483           0 :                 m0 = m_pullup(m0, sizeof(struct ieee80211_frame));
    1484           0 :                 if (m0 == NULL) {
    1485           0 :                         ifp->if_ierrors++;
    1486           0 :                         return (ENOBUFS);
    1487             :                 }
    1488             :         }
    1489           0 :         wh = mtod(m0, struct ieee80211_frame *);
    1490             : 
    1491           0 :         if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
    1492           0 :                 k = ieee80211_get_txkey(ic, wh, ni);
    1493           0 :                 if ((m0 = ieee80211_encrypt(ic, m0, k)) == NULL)
    1494           0 :                         return (ENOBUFS);
    1495             : 
    1496             :                 /* packet header may have moved, reset our local pointer */
    1497           0 :                 wh = mtod(m0, struct ieee80211_frame *);
    1498           0 :         }
    1499             : 
    1500             : #if NBPFILTER > 0
    1501           0 :         if (sc->sc_drvbpf != NULL) {
    1502           0 :                 struct mbuf mb;
    1503           0 :                 struct malo_tx_radiotap_hdr *tap = &sc->sc_txtap;
    1504             : 
    1505           0 :                 tap->wt_flags = 0;
    1506           0 :                 tap->wt_rate = sc->sc_last_txrate;
    1507           0 :                 tap->wt_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq);
    1508           0 :                 tap->wt_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags);
    1509             : 
    1510           0 :                 mb.m_data = (caddr_t)tap;
    1511           0 :                 mb.m_len = sc->sc_txtap_len;
    1512           0 :                 mb.m_next = m0;
    1513           0 :                 mb.m_nextpkt = NULL;
    1514           0 :                 mb.m_type = 0;
    1515           0 :                 mb.m_flags = 0;
    1516           0 :                 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT);
    1517           0 :         }
    1518             : #endif
    1519             : 
    1520             :         /*
    1521             :          * inject FW specific fields into the 802.11 frame
    1522             :          *
    1523             :          *  2 bytes FW len (inject)
    1524             :          * 24 bytes 802.11 frame header
    1525             :          *  6 bytes addr4 (inject)
    1526             :          *  n bytes 802.11 frame body
    1527             :          *
    1528             :          * For now copy all into a new mcluster.
    1529             :          */
    1530           0 :         MGETHDR(mnew, M_DONTWAIT, MT_DATA);
    1531           0 :         if (mnew == NULL)
    1532           0 :                 return (ENOBUFS);
    1533           0 :         MCLGET(mnew, M_DONTWAIT);
    1534           0 :         if (!(mnew->m_flags & M_EXT)) {
    1535           0 :                 m_free(mnew);
    1536           0 :                 return (ENOBUFS);
    1537             :         }
    1538             : 
    1539           0 :         *mtod(mnew, uint16_t *) = htole16(m0->m_pkthdr.len - 24); /* FW len */
    1540           0 :         bcopy(wh, mtod(mnew, caddr_t) + 2, sizeof(*wh));
    1541           0 :         bzero(mtod(mnew, caddr_t) + 26, 6);
    1542           0 :         m_copydata(m0, sizeof(*wh), m0->m_pkthdr.len - sizeof(*wh),
    1543           0 :             mtod(mnew, caddr_t) + 32);
    1544           0 :         mnew->m_pkthdr.len = mnew->m_len = m0->m_pkthdr.len + 8;
    1545           0 :         m_freem(m0);
    1546             :         m0 = mnew;
    1547             : 
    1548           0 :         error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m0,
    1549             :             BUS_DMA_NOWAIT);
    1550           0 :         if (error != 0) {
    1551           0 :                 printf("%s: can't map mbuf (error %d)\n",
    1552           0 :                     sc->sc_dev.dv_xname, error);
    1553           0 :                 m_freem(m0);
    1554           0 :                 return (error);
    1555             :         }
    1556             : 
    1557           0 :         data->m = m0;
    1558           0 :         data->ni = ni;
    1559           0 :         data->softstat |= htole32(0x80);
    1560             : 
    1561           0 :         malo_tx_setup_desc(sc, desc, m0->m_pkthdr.len, 1,
    1562           0 :             data->map->dm_segs, data->map->dm_nsegs);
    1563             : 
    1564           0 :         bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,
    1565             :             BUS_DMASYNC_PREWRITE);
    1566           0 :         bus_dmamap_sync(sc->sc_dmat, sc->sc_txring.map,
    1567             :             sc->sc_txring.cur * sizeof(struct malo_tx_desc),
    1568             :             sizeof(struct malo_tx_desc), BUS_DMASYNC_PREWRITE);
    1569             : 
    1570             :         DPRINTF(2, "%s: sending data frame, pktlen=%u, idx=%u\n",
    1571             :             sc->sc_dev.dv_xname, m0->m_pkthdr.len, sc->sc_txring.cur);
    1572             : 
    1573           0 :         sc->sc_txring.queued++;
    1574           0 :         sc->sc_txring.cur = (sc->sc_txring.cur + 1) % MALO_TX_RING_COUNT;
    1575             : 
    1576             :         /* kick data TX */
    1577           0 :         malo_ctl_write4(sc, 0x0c18, 1);
    1578           0 :         malo_ctl_barrier(sc, BUS_SPACE_BARRIER_WRITE);
    1579             : 
    1580           0 :         return (0);
    1581           0 : }
    1582             : 
    1583             : void
    1584           0 : malo_tx_setup_desc(struct malo_softc *sc, struct malo_tx_desc *desc,
    1585             :     int len, int rate, const bus_dma_segment_t *segs, int nsegs)
    1586             : {
    1587           0 :         desc->len = htole16(segs[0].ds_len);
    1588           0 :         desc->datarate = rate; /* 0 = mgmt frame, 1 = data frame */
    1589           0 :         desc->physdata = htole32(segs[0].ds_addr);
    1590           0 :         desc->status = htole32(0x00000001 | 0x80000000);
    1591           0 : }
    1592             : 
    1593             : void
    1594           0 : malo_rx_intr(struct malo_softc *sc)
    1595             : {
    1596           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1597           0 :         struct ifnet *ifp = &ic->ic_if;
    1598             :         struct malo_rx_desc *desc;
    1599             :         struct malo_rx_data *data;
    1600             :         struct ieee80211_frame *wh;
    1601           0 :         struct ieee80211_rxinfo rxi;
    1602             :         struct ieee80211_node *ni;
    1603             :         struct mbuf *mnew, *m;
    1604             :         uint32_t rxRdPtr, rxWrPtr;
    1605             :         int error, i;
    1606             : 
    1607           0 :         rxRdPtr = malo_mem_read4(sc, sc->sc_RxPdRdPtr);
    1608           0 :         rxWrPtr = malo_mem_read4(sc, sc->sc_RxPdWrPtr);
    1609             : 
    1610           0 :         for (i = 0; i < MALO_RX_RING_COUNT && rxRdPtr != rxWrPtr; i++) {
    1611           0 :                 desc = &sc->sc_rxring.desc[sc->sc_rxring.cur];
    1612           0 :                 data = &sc->sc_rxring.data[sc->sc_rxring.cur];
    1613             : 
    1614           0 :                 bus_dmamap_sync(sc->sc_dmat, sc->sc_rxring.map,
    1615             :                     sc->sc_rxring.cur * sizeof(struct malo_rx_desc),
    1616             :                     sizeof(struct malo_rx_desc), BUS_DMASYNC_POSTREAD);
    1617             : 
    1618             :                 DPRINTF(3, "%s: rx intr idx=%d, rxctrl=0x%02x, rssi=%d, "
    1619             :                     "status=0x%02x, channel=%d, len=%d, res1=%02x, rate=%d, "
    1620             :                     "physdata=0x%04x, physnext=0x%04x, qosctrl=%02x, res2=%d\n",
    1621             :                     sc->sc_dev.dv_xname,
    1622             :                     sc->sc_rxring.cur, desc->rxctrl, desc->rssi, desc->status,
    1623             :                     desc->channel, letoh16(desc->len), desc->reserved1,
    1624             :                     desc->datarate, letoh32(desc->physdata),
    1625             :                     letoh32(desc->physnext), desc->qosctrl, desc->reserved2);
    1626             : 
    1627           0 :                 if ((desc->rxctrl & 0x80) == 0)
    1628             :                         break;
    1629             : 
    1630           0 :                 MGETHDR(mnew, M_DONTWAIT, MT_DATA);
    1631           0 :                 if (mnew == NULL) {
    1632           0 :                         ifp->if_ierrors++;
    1633           0 :                         goto skip;
    1634             :                 }
    1635             : 
    1636           0 :                 MCLGET(mnew, M_DONTWAIT);
    1637           0 :                 if (!(mnew->m_flags & M_EXT)) {
    1638           0 :                         m_freem(mnew);
    1639           0 :                         ifp->if_ierrors++;
    1640           0 :                         goto skip;
    1641             :                 }
    1642             : 
    1643           0 :                 bus_dmamap_sync(sc->sc_dmat, data->map, 0,
    1644             :                     data->map->dm_mapsize, BUS_DMASYNC_POSTREAD);
    1645           0 :                 bus_dmamap_unload(sc->sc_dmat, data->map);
    1646             : 
    1647           0 :                 error = bus_dmamap_load(sc->sc_dmat, data->map,
    1648             :                     mtod(mnew, void *), MCLBYTES, NULL, BUS_DMA_NOWAIT);
    1649           0 :                 if (error != 0) {
    1650           0 :                         m_freem(mnew);
    1651             : 
    1652           0 :                         error = bus_dmamap_load(sc->sc_dmat, data->map,
    1653             :                             mtod(data->m, void *), MCLBYTES, NULL,
    1654             :                             BUS_DMA_NOWAIT);
    1655           0 :                         if (error != 0) {
    1656           0 :                                 panic("%s: could not load old rx mbuf",
    1657           0 :                                     sc->sc_dev.dv_xname);
    1658             :                         }
    1659           0 :                         ifp->if_ierrors++;
    1660           0 :                         goto skip;
    1661             :                 }
    1662             : 
    1663             :                 /*
    1664             :                  * New mbuf mbuf successfully loaded
    1665             :                  */
    1666           0 :                 m = data->m;
    1667           0 :                 data->m = mnew;
    1668           0 :                 desc->physdata = htole32(data->map->dm_segs->ds_addr);
    1669             : 
    1670             :                 /* finalize mbuf */
    1671           0 :                 m->m_pkthdr.len = m->m_len = letoh16(desc->len);
    1672             : 
    1673             :                 /*
    1674             :                  * cut out FW specific fields from the 802.11 frame
    1675             :                  *
    1676             :                  *  2 bytes FW len (cut out)
    1677             :                  * 24 bytes 802.11 frame header
    1678             :                  *  6 bytes addr4 (cut out)
    1679             :                  *  n bytes 802.11 frame data
    1680             :                  */
    1681           0 :                 bcopy(m->m_data, m->m_data + 6, 26);
    1682           0 :                 m_adj(m, 8);
    1683             : 
    1684             : #if NBPFILTER > 0
    1685           0 :                 if (sc->sc_drvbpf != NULL) {
    1686           0 :                         struct mbuf mb;
    1687           0 :                         struct malo_rx_radiotap_hdr *tap = &sc->sc_rxtap;
    1688             : 
    1689           0 :                         tap->wr_flags = 0;
    1690           0 :                         tap->wr_chan_freq =
    1691           0 :                             htole16(ic->ic_bss->ni_chan->ic_freq);
    1692           0 :                         tap->wr_chan_flags =
    1693           0 :                             htole16(ic->ic_bss->ni_chan->ic_flags);
    1694           0 :                         tap->wr_rssi = desc->rssi;
    1695           0 :                         tap->wr_max_rssi = ic->ic_max_rssi;
    1696             : 
    1697           0 :                         mb.m_data = (caddr_t)tap;
    1698           0 :                         mb.m_len = sc->sc_rxtap_len;
    1699           0 :                         mb.m_next = m;
    1700           0 :                         mb.m_nextpkt = NULL;
    1701           0 :                         mb.m_type = 0;
    1702           0 :                         mb.m_flags = 0;
    1703           0 :                         bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN);
    1704           0 :                 }
    1705             : #endif
    1706             : 
    1707           0 :                 wh = mtod(m, struct ieee80211_frame *);
    1708           0 :                 ni = ieee80211_find_rxnode(ic, wh);
    1709             : 
    1710             :                 /* send the frame to the 802.11 layer */
    1711           0 :                 rxi.rxi_flags = 0;
    1712           0 :                 rxi.rxi_rssi = desc->rssi;
    1713           0 :                 rxi.rxi_tstamp = 0;     /* unused */
    1714           0 :                 ieee80211_input(ifp, m, ni, &rxi);
    1715             : 
    1716             :                 /* node is no longer needed */
    1717           0 :                 ieee80211_release_node(ic, ni);
    1718             : 
    1719             : skip:
    1720           0 :                 desc->rxctrl = 0;
    1721           0 :                 rxRdPtr = letoh32(desc->physnext);
    1722             : 
    1723           0 :                 bus_dmamap_sync(sc->sc_dmat, sc->sc_rxring.map,
    1724             :                     sc->sc_rxring.cur * sizeof(struct malo_rx_desc),
    1725             :                     sizeof(struct malo_rx_desc), BUS_DMASYNC_PREWRITE);
    1726             : 
    1727           0 :                 sc->sc_rxring.cur = (sc->sc_rxring.cur + 1) %
    1728             :                     MALO_RX_RING_COUNT;
    1729             :         }
    1730             : 
    1731           0 :         malo_mem_write4(sc, sc->sc_RxPdRdPtr, rxRdPtr);
    1732           0 : }
    1733             : 
    1734             : int
    1735           0 : malo_load_bootimg(struct malo_softc *sc)
    1736             : {
    1737             :         char *name = "malo8335-h";
    1738           0 :         uint8_t *ucode;
    1739           0 :         size_t usize;
    1740             :         int error, i;
    1741             : 
    1742             :         /* load boot firmware */
    1743           0 :         if ((error = loadfirmware(name, &ucode, &usize)) != 0) {
    1744           0 :                 printf("%s: error %d, could not read firmware %s\n",
    1745           0 :                     sc->sc_dev.dv_xname, error, name);
    1746           0 :                 return (EIO);
    1747             :         }
    1748             : 
    1749             :         /*
    1750             :          * It seems we are putting this code directly onto the stack of
    1751             :          * the ARM cpu. I don't know why we need to instruct the DMA
    1752             :          * engine to move the code. This is a big riddle without docu.
    1753             :          */
    1754             :         DPRINTF(1, "%s: loading boot firmware\n", sc->sc_dev.dv_xname);
    1755           0 :         malo_mem_write2(sc, 0xbef8, 0x001);
    1756           0 :         malo_mem_write2(sc, 0xbefa, usize);
    1757           0 :         malo_mem_write4(sc, 0xbefc, 0);
    1758             : 
    1759           0 :         bus_space_write_region_1(sc->sc_mem1_bt, sc->sc_mem1_bh, 0xbf00,
    1760             :             ucode, usize);
    1761             : 
    1762             :         /*
    1763             :          * we loaded the firmware into card memory now tell the CPU
    1764             :          * to fetch the code and execute it. The memory mapped via the
    1765             :          * first bar is internaly mapped to 0xc0000000.
    1766             :          */
    1767           0 :         malo_send_cmd(sc, 0xc000bef8);
    1768             : 
    1769             :         /* wait for the device to go into FW loading mode */
    1770           0 :         for (i = 0; i < 10; i++) {
    1771           0 :                 delay(50);
    1772           0 :                 malo_ctl_barrier(sc, BUS_SPACE_BARRIER_READ);
    1773           0 :                 if (malo_ctl_read4(sc, 0x0c14) == 0x5)
    1774             :                         break;
    1775             :         }
    1776           0 :         if (i == 10) {
    1777           0 :                 printf("%s: timeout at boot firmware load!\n",
    1778           0 :                     sc->sc_dev.dv_xname);
    1779           0 :                 free(ucode, M_DEVBUF, usize);
    1780           0 :                 return (ETIMEDOUT);
    1781             :         }
    1782           0 :         free(ucode, M_DEVBUF, usize);
    1783             : 
    1784             :         /* tell the card we're done and... */
    1785           0 :         malo_mem_write2(sc, 0xbef8, 0x001);
    1786           0 :         malo_mem_write2(sc, 0xbefa, 0);
    1787           0 :         malo_mem_write4(sc, 0xbefc, 0);
    1788           0 :         malo_send_cmd(sc, 0xc000bef8);
    1789             : 
    1790             :         DPRINTF(1, "%s: boot firmware loaded\n", sc->sc_dev.dv_xname);
    1791             : 
    1792           0 :         return (0);
    1793           0 : }
    1794             : 
    1795             : int
    1796           0 : malo_load_firmware(struct malo_softc *sc)
    1797             : {
    1798             :         struct malo_cmdheader *hdr;
    1799             :         char *name = "malo8335-m";
    1800             :         void *data;
    1801           0 :         uint8_t *ucode;
    1802           0 :         size_t size, count, bsize;
    1803             :         int i, sn, error;
    1804             : 
    1805             :         /* load real firmware now */
    1806           0 :         if ((error = loadfirmware(name, &ucode, &size)) != 0) {
    1807           0 :                 printf("%s: error %d, could not read firmware %s\n",
    1808           0 :                     sc->sc_dev.dv_xname, error, name);
    1809           0 :                 return (EIO);
    1810             :         }
    1811             : 
    1812             :         DPRINTF(1, "%s: uploading firmware\n", sc->sc_dev.dv_xname);
    1813             : 
    1814           0 :         hdr = sc->sc_cmd_mem;
    1815           0 :         data = hdr + 1;
    1816             :         sn = 1;
    1817           0 :         for (count = 0; count < size; count += bsize) {
    1818           0 :                 bsize = MIN(256, size - count);
    1819             : 
    1820           0 :                 hdr->cmd = htole16(0x0001);
    1821           0 :                 hdr->size = htole16(bsize);
    1822           0 :                 hdr->seqnum = htole16(sn++);
    1823           0 :                 hdr->result = 0;
    1824             : 
    1825           0 :                 bcopy(ucode + count, data, bsize);
    1826             : 
    1827           0 :                 bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
    1828             :                     BUS_DMASYNC_PREWRITE);
    1829           0 :                 malo_send_cmd(sc, sc->sc_cmd_dmaaddr);
    1830           0 :                 bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
    1831             :                     BUS_DMASYNC_POSTWRITE);
    1832           0 :                 delay(500);
    1833             :         }
    1834           0 :         free(ucode, M_DEVBUF, size);
    1835             : 
    1836             :         DPRINTF(1, "%s: firmware upload finished\n", sc->sc_dev.dv_xname);
    1837             : 
    1838             :         /*
    1839             :          * send a command with size 0 to tell that the firmware has been
    1840             :          * uploaded
    1841             :          */
    1842           0 :         hdr->cmd = htole16(0x0001);
    1843           0 :         hdr->size = 0;
    1844           0 :         hdr->seqnum = htole16(sn++);
    1845           0 :         hdr->result = 0;
    1846             : 
    1847           0 :         bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
    1848             :             BUS_DMASYNC_PREWRITE);
    1849           0 :         malo_send_cmd(sc, sc->sc_cmd_dmaaddr);
    1850           0 :         bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
    1851             :             BUS_DMASYNC_POSTWRITE);
    1852           0 :         delay(100);
    1853             : 
    1854             :         DPRINTF(1, "%s: loading firmware\n", sc->sc_dev.dv_xname);
    1855             : 
    1856             :         /* wait until firmware has been loaded */
    1857           0 :         for (i = 0; i < 200; i++) {
    1858           0 :                 malo_ctl_write4(sc, 0x0c10, 0x5a);
    1859           0 :                 delay(500);
    1860           0 :                 malo_ctl_barrier(sc, BUS_SPACE_BARRIER_WRITE |
    1861             :                      BUS_SPACE_BARRIER_READ);
    1862           0 :                 if (malo_ctl_read4(sc, 0x0c14) == 0xf0f1f2f4)
    1863             :                         break;
    1864             :         }
    1865           0 :         if (i == 200) {
    1866           0 :                 printf("%s: timeout at firmware load!\n", sc->sc_dev.dv_xname);
    1867           0 :                 return (ETIMEDOUT);
    1868             :         }
    1869             : 
    1870             :         DPRINTF(1, "%s: firmware loaded\n", sc->sc_dev.dv_xname);
    1871             : 
    1872           0 :         return (0);
    1873           0 : }
    1874             : 
    1875             : int
    1876           0 : malo_set_slot(struct malo_softc *sc)
    1877             : {
    1878           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1879             : 
    1880           0 :         if (ic->ic_flags & IEEE80211_F_SHSLOT) {
    1881             :                 /* set short slot */
    1882           0 :                 if (malo_cmd_set_slot(sc, 1)) {
    1883           0 :                         printf("%s: setting short slot failed\n",
    1884           0 :                             sc->sc_dev.dv_xname);
    1885           0 :                         return (ENXIO);
    1886             :                 }
    1887             :         } else {
    1888             :                 /* set long slot */
    1889           0 :                 if (malo_cmd_set_slot(sc, 0)) {
    1890           0 :                         printf("%s: setting long slot failed\n",
    1891           0 :                             sc->sc_dev.dv_xname);
    1892           0 :                         return (ENXIO);
    1893             :                 }
    1894             :         }
    1895             : 
    1896           0 :         return (0);
    1897           0 : }
    1898             : 
    1899             : void
    1900           0 : malo_update_slot(struct ieee80211com *ic)
    1901             : {
    1902           0 :         struct malo_softc *sc = ic->ic_if.if_softc;
    1903             : 
    1904           0 :         malo_set_slot(sc);
    1905             : 
    1906             : #ifndef IEEE80211_STA_ONLY
    1907           0 :         if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
    1908             :                 /* TODO */
    1909             :         }
    1910             : #endif
    1911           0 : }
    1912             : 
    1913             : #ifdef MALO_DEBUG
    1914             : void
    1915             : malo_hexdump(void *buf, int len)
    1916             : {
    1917             :         u_char b[16];
    1918             :         int i, j, l;
    1919             : 
    1920             :         for (i = 0; i < len; i += l) {
    1921             :                 printf("%4i:", i);
    1922             :                 l = min(sizeof(b), len - i);
    1923             :                 bcopy(buf + i, b, l);
    1924             :                 
    1925             :                 for (j = 0; j < sizeof(b); j++) {
    1926             :                         if (j % 2 == 0)
    1927             :                                 printf(" ");
    1928             :                         if (j % 8 == 0)
    1929             :                                 printf(" ");
    1930             :                         if (j < l)
    1931             :                                 printf("%02x", (int)b[j]);
    1932             :                         else
    1933             :                                 printf("  ");
    1934             :                 }
    1935             :                 printf("  |");
    1936             :                 for (j = 0; j < l; j++) {
    1937             :                         if (b[j] >= 0x20 && b[j] <= 0x7e)
    1938             :                                 printf("%c", b[j]);
    1939             :                         else
    1940             :                                 printf(".");
    1941             :                 }
    1942             :                 printf("|\n");
    1943             :         }
    1944             : }
    1945             : #endif
    1946             : 
    1947             : static char *
    1948           0 : malo_cmd_string(uint16_t cmd)
    1949             : {
    1950             :         int i;
    1951             :         static char cmd_buf[16];
    1952             :         static const struct {
    1953             :                 uint16_t         cmd_code;
    1954             :                 char            *cmd_string;
    1955             :         } cmds[] = {
    1956             :                 { MALO_CMD_GET_HW_SPEC,         "GetHwSpecifications" },
    1957             :                 { MALO_CMD_SET_RADIO,           "SetRadio"            },
    1958             :                 { MALO_CMD_SET_AID,             "SetAid"              },
    1959             :                 { MALO_CMD_SET_TXPOWER,         "SetTxPower"          },
    1960             :                 { MALO_CMD_SET_ANTENNA,         "SetAntenna"          },
    1961             :                 { MALO_CMD_SET_PRESCAN,         "SetPrescan"          },
    1962             :                 { MALO_CMD_SET_POSTSCAN,        "SetPostscan"         },
    1963             :                 { MALO_CMD_SET_RATE,            "SetRate"             },
    1964             :                 { MALO_CMD_SET_CHANNEL,         "SetChannel"          },
    1965             :                 { MALO_CMD_SET_RTS,             "SetRTS"              },
    1966             :                 { MALO_CMD_SET_SLOT,            "SetSlot"             },
    1967             :         };
    1968             : 
    1969           0 :         for (i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++)
    1970           0 :                 if ((letoh16(cmd) & 0x7fff) == cmds[i].cmd_code)
    1971           0 :                         return (cmds[i].cmd_string);
    1972             : 
    1973           0 :         snprintf(cmd_buf, sizeof(cmd_buf), "unknown %#x", cmd);
    1974           0 :         return (cmd_buf);
    1975           0 : }
    1976             : 
    1977             : static char *
    1978           0 : malo_cmd_string_result(uint16_t result)
    1979             : {
    1980             :         int i;
    1981             :         static const struct {
    1982             :                 uint16_t         result_code;
    1983             :                 char            *result_string;
    1984             :         } results[] = {
    1985             :                 { MALO_CMD_RESULT_OK,           "OK"          },
    1986             :                 { MALO_CMD_RESULT_ERROR,        "general error"       },
    1987             :                 { MALO_CMD_RESULT_NOSUPPORT,    "not supported" },
    1988             :                 { MALO_CMD_RESULT_PENDING,      "pending"     },
    1989             :                 { MALO_CMD_RESULT_BUSY,         "ignored"     },
    1990             :                 { MALO_CMD_RESULT_PARTIALDATA,  "incomplete"  },
    1991             :         };
    1992             : 
    1993           0 :         for (i = 0; i < sizeof(results) / sizeof(results[0]); i++)
    1994           0 :                 if (letoh16(result) == results[i].result_code)
    1995           0 :                         return (results[i].result_string);
    1996             : 
    1997           0 :         return ("unknown");
    1998           0 : }
    1999             : 
    2000             : int
    2001           0 : malo_cmd_get_spec(struct malo_softc *sc)
    2002             : {
    2003           0 :         struct malo_cmdheader *hdr = sc->sc_cmd_mem;
    2004             :         struct malo_hw_spec *spec;
    2005             : 
    2006           0 :         hdr->cmd = htole16(MALO_CMD_GET_HW_SPEC);
    2007           0 :         hdr->size = htole16(sizeof(*hdr) + sizeof(*spec));
    2008           0 :         hdr->seqnum = htole16(42);   /* the one and only */
    2009           0 :         hdr->result = 0;
    2010           0 :         spec = (struct malo_hw_spec *)(hdr + 1);
    2011             : 
    2012           0 :         bzero(spec, sizeof(*spec));
    2013           0 :         memset(spec->PermanentAddress, 0xff, ETHER_ADDR_LEN);
    2014           0 :         spec->CookiePtr = htole32(sc->sc_cookie_dmaaddr);
    2015             : 
    2016           0 :         bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
    2017             :             BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
    2018             : 
    2019           0 :         if (malo_send_cmd_dma(sc, sc->sc_cmd_dmaaddr) != 0)
    2020           0 :                 return (ETIMEDOUT);
    2021             : 
    2022             :         /* get the data from the buffer */
    2023             :         DPRINTF(1, "%s: get_hw_spec: V%x R%x, #WCB %d, #Mcast %d, Regcode %d, "
    2024             :             "#Ant %d\n", sc->sc_dev.dv_xname, htole16(spec->HwVersion),
    2025             :             htole32(spec->FWReleaseNumber), htole16(spec->NumOfWCB),
    2026             :             htole16(spec->NumOfMCastAdr), htole16(spec->RegionCode),
    2027             :             htole16(spec->NumberOfAntenna));
    2028             : 
    2029             :         /* tell the DMA engine where our rings are */
    2030           0 :         malo_mem_write4(sc, letoh32(spec->RxPdRdPtr) & 0xffff,
    2031             :             sc->sc_rxring.physaddr);
    2032           0 :         malo_mem_write4(sc, letoh32(spec->RxPdWrPtr) & 0xffff,
    2033             :             sc->sc_rxring.physaddr);
    2034           0 :         malo_mem_write4(sc, letoh32(spec->WcbBase0) & 0xffff,
    2035             :             sc->sc_txring.physaddr);
    2036             : 
    2037             :         /* save DMA RX pointers for later use */
    2038           0 :         sc->sc_RxPdRdPtr = letoh32(spec->RxPdRdPtr) & 0xffff;
    2039           0 :         sc->sc_RxPdWrPtr = letoh32(spec->RxPdWrPtr) & 0xffff;
    2040             : 
    2041           0 :         return (0);
    2042           0 : }
    2043             : 
    2044             : int
    2045           0 : malo_cmd_set_prescan(struct malo_softc *sc)
    2046             : {
    2047           0 :         struct malo_cmdheader *hdr = sc->sc_cmd_mem;
    2048             : 
    2049           0 :         hdr->cmd = htole16(MALO_CMD_SET_PRESCAN);
    2050           0 :         hdr->size = htole16(sizeof(*hdr));
    2051           0 :         hdr->seqnum = 1;
    2052           0 :         hdr->result = 0;
    2053             : 
    2054           0 :         bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
    2055             :             BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
    2056             : 
    2057           0 :         return (malo_send_cmd_dma(sc, sc->sc_cmd_dmaaddr));
    2058             : }
    2059             : 
    2060             : int
    2061           0 : malo_cmd_set_postscan(struct malo_softc *sc, uint8_t *macaddr, uint8_t ibsson)
    2062             : {
    2063           0 :         struct malo_cmdheader *hdr = sc->sc_cmd_mem;
    2064             :         struct malo_cmd_postscan *body;
    2065             : 
    2066           0 :         hdr->cmd = htole16(MALO_CMD_SET_POSTSCAN);
    2067           0 :         hdr->size = htole16(sizeof(*hdr) + sizeof(*body));
    2068           0 :         hdr->seqnum = 1;
    2069           0 :         hdr->result = 0;
    2070           0 :         body = (struct malo_cmd_postscan *)(hdr + 1);
    2071             : 
    2072           0 :         bzero(body, sizeof(*body));
    2073           0 :         memcpy(&body->bssid, macaddr, ETHER_ADDR_LEN);
    2074           0 :         body->isibss = htole32(ibsson);
    2075             : 
    2076           0 :         bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
    2077             :             BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
    2078             : 
    2079           0 :         return (malo_send_cmd_dma(sc, sc->sc_cmd_dmaaddr));
    2080             : }
    2081             : 
    2082             : int
    2083           0 : malo_cmd_set_channel(struct malo_softc *sc, uint8_t channel)
    2084             : {
    2085           0 :         struct malo_cmdheader *hdr = sc->sc_cmd_mem;
    2086             :         struct malo_cmd_channel *body;
    2087             : 
    2088           0 :         hdr->cmd = htole16(MALO_CMD_SET_CHANNEL);
    2089           0 :         hdr->size = htole16(sizeof(*hdr) + sizeof(*body));
    2090           0 :         hdr->seqnum = 1;
    2091           0 :         hdr->result = 0;
    2092           0 :         body = (struct malo_cmd_channel *)(hdr + 1);
    2093             : 
    2094           0 :         bzero(body, sizeof(*body));
    2095           0 :         body->action = htole16(1);
    2096           0 :         body->channel = channel;
    2097             : 
    2098           0 :         bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
    2099             :             BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
    2100             : 
    2101           0 :         return (malo_send_cmd_dma(sc, sc->sc_cmd_dmaaddr));
    2102             : }
    2103             : 
    2104             : int
    2105           0 : malo_cmd_set_antenna(struct malo_softc *sc, uint16_t antenna)
    2106             : {
    2107           0 :         struct malo_cmdheader *hdr = sc->sc_cmd_mem;
    2108             :         struct malo_cmd_antenna *body;
    2109             : 
    2110           0 :         hdr->cmd = htole16(MALO_CMD_SET_ANTENNA);
    2111           0 :         hdr->size = htole16(sizeof(*hdr) + sizeof(*body));
    2112           0 :         hdr->seqnum = 1;
    2113           0 :         hdr->result = 0;
    2114           0 :         body = (struct malo_cmd_antenna *)(hdr + 1);
    2115             : 
    2116           0 :         bzero(body, sizeof(*body));
    2117           0 :         body->action = htole16(antenna);
    2118           0 :         if (antenna == 1)
    2119           0 :                 body->mode = htole16(0xffff);
    2120             :         else
    2121           0 :                 body->mode = htole16(2);
    2122             : 
    2123           0 :         bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
    2124             :             BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
    2125             : 
    2126           0 :         return (malo_send_cmd_dma(sc, sc->sc_cmd_dmaaddr));
    2127             : }
    2128             : 
    2129             : int
    2130           0 : malo_cmd_set_radio(struct malo_softc *sc, uint16_t enable,
    2131             :     uint16_t preamble_mode)
    2132             : {
    2133           0 :         struct malo_cmdheader *hdr = sc->sc_cmd_mem;
    2134             :         struct malo_cmd_radio *body;
    2135             : 
    2136           0 :         hdr->cmd = htole16(MALO_CMD_SET_RADIO);
    2137           0 :         hdr->size = htole16(sizeof(*hdr) + sizeof(*body));
    2138           0 :         hdr->seqnum = 1;
    2139           0 :         hdr->result = 0;
    2140           0 :         body = (struct malo_cmd_radio *)(hdr + 1);
    2141             : 
    2142           0 :         bzero(body, sizeof(*body));
    2143           0 :         body->action = htole16(1);
    2144           0 :         body->preamble_mode = htole16(preamble_mode);
    2145           0 :         body->enable = htole16(enable);
    2146             : 
    2147           0 :         bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
    2148             :             BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
    2149             : 
    2150           0 :         return (malo_send_cmd_dma(sc, sc->sc_cmd_dmaaddr));
    2151             : }
    2152             : 
    2153             : int
    2154           0 : malo_cmd_set_aid(struct malo_softc *sc, uint8_t *bssid, uint16_t associd)
    2155             : {
    2156           0 :         struct malo_cmdheader *hdr = sc->sc_cmd_mem;
    2157             :         struct malo_cmd_aid *body;
    2158             : 
    2159           0 :         hdr->cmd = htole16(MALO_CMD_SET_AID);
    2160           0 :         hdr->size = htole16(sizeof(*hdr) + sizeof(*body));
    2161           0 :         hdr->seqnum = 1;
    2162           0 :         hdr->result = 0;
    2163           0 :         body = (struct malo_cmd_aid *)(hdr + 1);
    2164             : 
    2165           0 :         bzero(body, sizeof(*body));
    2166           0 :         body->associd = htole16(associd);
    2167           0 :         memcpy(&body->macaddr[0], bssid, IEEE80211_ADDR_LEN);
    2168             : 
    2169           0 :         bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
    2170             :             BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
    2171             : 
    2172           0 :         return (malo_send_cmd_dma(sc, sc->sc_cmd_dmaaddr));
    2173             : }
    2174             : 
    2175             : int
    2176           0 : malo_cmd_set_txpower(struct malo_softc *sc, unsigned int powerlevel)
    2177             : {
    2178           0 :         struct malo_cmdheader *hdr = sc->sc_cmd_mem;
    2179             :         struct malo_cmd_txpower *body;
    2180             : 
    2181           0 :         hdr->cmd = htole16(MALO_CMD_SET_TXPOWER);
    2182           0 :         hdr->size = htole16(sizeof(*hdr) + sizeof(*body));
    2183           0 :         hdr->seqnum = 1;
    2184           0 :         hdr->result = 0;
    2185           0 :         body = (struct malo_cmd_txpower *)(hdr + 1);
    2186             : 
    2187           0 :         bzero(body, sizeof(*body));
    2188           0 :         body->action = htole16(1);
    2189           0 :         if (powerlevel < 30)
    2190           0 :                 body->supportpowerlvl = htole16(5);  /* LOW */
    2191           0 :         else if (powerlevel >= 30 && powerlevel < 60)
    2192           0 :                 body->supportpowerlvl = htole16(10); /* MEDIUM */
    2193             :         else
    2194           0 :                 body->supportpowerlvl = htole16(15); /* HIGH */
    2195             : 
    2196           0 :         bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
    2197             :             BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
    2198             : 
    2199           0 :         return (malo_send_cmd_dma(sc, sc->sc_cmd_dmaaddr));
    2200             : }
    2201             : 
    2202             : int
    2203           0 : malo_cmd_set_rts(struct malo_softc *sc, uint32_t threshold)
    2204             : {
    2205           0 :         struct malo_cmdheader *hdr = sc->sc_cmd_mem;
    2206             :         struct malo_cmd_rts *body;
    2207             : 
    2208           0 :         hdr->cmd = htole16(MALO_CMD_SET_RTS);
    2209           0 :         hdr->size = htole16(sizeof(*hdr) + sizeof(*body));
    2210           0 :         hdr->seqnum = 1;
    2211           0 :         hdr->result = 0;
    2212           0 :         body = (struct malo_cmd_rts *)(hdr + 1);
    2213             : 
    2214           0 :         bzero(body, sizeof(*body));
    2215           0 :         body->action = htole16(1);
    2216           0 :         body->threshold = htole32(threshold);
    2217             : 
    2218           0 :         bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
    2219             :             BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
    2220             : 
    2221           0 :         return (malo_send_cmd_dma(sc, sc->sc_cmd_dmaaddr));
    2222             : }
    2223             : 
    2224             : int
    2225           0 : malo_cmd_set_slot(struct malo_softc *sc, uint8_t slot)
    2226             : {
    2227           0 :         struct malo_cmdheader *hdr = sc->sc_cmd_mem;
    2228             :         struct malo_cmd_slot *body;
    2229             : 
    2230           0 :         hdr->cmd = htole16(MALO_CMD_SET_SLOT);
    2231           0 :         hdr->size = htole16(sizeof(*hdr) + sizeof(*body));
    2232           0 :         hdr->seqnum = 1;
    2233           0 :         hdr->result = 0;
    2234           0 :         body = (struct malo_cmd_slot *)(hdr + 1);
    2235             : 
    2236           0 :         bzero(body, sizeof(*body));
    2237           0 :         body->action = htole16(1);
    2238           0 :         body->slot = slot;
    2239             : 
    2240           0 :         bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
    2241             :             BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
    2242             : 
    2243           0 :         return (malo_send_cmd_dma(sc, sc->sc_cmd_dmaaddr));
    2244             : }
    2245             : 
    2246             : int
    2247           0 : malo_cmd_set_rate(struct malo_softc *sc, uint8_t rate)
    2248             : {
    2249           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2250           0 :         struct malo_cmdheader *hdr = sc->sc_cmd_mem;
    2251             :         struct malo_cmd_rate *body;
    2252             :         int i;
    2253             : 
    2254           0 :         hdr->cmd = htole16(MALO_CMD_SET_RATE);
    2255           0 :         hdr->size = htole16(sizeof(*hdr) + sizeof(*body));
    2256           0 :         hdr->seqnum = 1;
    2257           0 :         hdr->result = 0;
    2258           0 :         body = (struct malo_cmd_rate *)(hdr + 1);
    2259             : 
    2260           0 :         bzero(body, sizeof(*body));
    2261             : 
    2262             : #ifndef IEEE80211_STA_ONLY
    2263           0 :         if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
    2264             :                 /* TODO */
    2265             :         } else
    2266             : #endif
    2267             :         {
    2268           0 :                 body->aprates[0] = 2;
    2269           0 :                 body->aprates[1] = 4;
    2270           0 :                 body->aprates[2] = 11;
    2271           0 :                 body->aprates[3] = 22;
    2272           0 :                 if (ic->ic_curmode == IEEE80211_MODE_11G) {
    2273           0 :                         body->aprates[4] = 0;
    2274           0 :                         body->aprates[5] = 12;
    2275           0 :                         body->aprates[6] = 18;
    2276           0 :                         body->aprates[7] = 24;
    2277           0 :                         body->aprates[8] = 36;
    2278           0 :                         body->aprates[9] = 48;
    2279           0 :                         body->aprates[10] = 72;
    2280           0 :                         body->aprates[11] = 96;
    2281           0 :                         body->aprates[12] = 108;
    2282           0 :                 }
    2283             :         }
    2284             : 
    2285           0 :         if (rate != 0) {
    2286             :                 /* fixed rate */
    2287           0 :                 for (i = 0; i < 13; i++) {
    2288           0 :                         if (body->aprates[i] == rate) {
    2289           0 :                                 body->rateindex = i;
    2290           0 :                                 body->dataratetype = 1;
    2291           0 :                                 break;
    2292             :                         }
    2293             :                 }
    2294             :         }
    2295             : 
    2296           0 :         bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
    2297             :             BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
    2298             : 
    2299           0 :         return (malo_send_cmd_dma(sc, sc->sc_cmd_dmaaddr));
    2300             : }
    2301             : 
    2302             : void
    2303           0 : malo_cmd_response(struct malo_softc *sc)
    2304             : {
    2305           0 :         struct malo_cmdheader *hdr = sc->sc_cmd_mem;
    2306             : 
    2307           0 :         if (letoh16(hdr->result) != MALO_CMD_RESULT_OK) {
    2308           0 :                 printf("%s: firmware cmd %s failed with %s\n",
    2309           0 :                     sc->sc_dev.dv_xname,
    2310           0 :                     malo_cmd_string(hdr->cmd),
    2311           0 :                     malo_cmd_string_result(hdr->result));
    2312           0 :         }
    2313             : 
    2314             : #ifdef MALO_DEBUG
    2315             :         printf("%s: cmd answer for %s=%s\n",
    2316             :             sc->sc_dev.dv_xname,
    2317             :             malo_cmd_string(hdr->cmd),
    2318             :             malo_cmd_string_result(hdr->result));
    2319             : 
    2320             :         if (malo_d > 2)
    2321             :                 malo_hexdump(hdr, letoh16(hdr->size));
    2322             : #endif
    2323           0 : }

Generated by: LCOV version 1.13