The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/malo/if_malohal.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2007 Marvell Semiconductor, Inc.
    3  * Copyright (c) 2007 Sam Leffler, Errno Consulting
    4  * Copyright (c) 2008 Weongyo Jeong <weongyo@freebsd.org>
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer,
   12  *    without modification.
   13  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
   14  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
   15  *    redistribution must be conditioned upon including a substantially
   16  *    similar Disclaimer requirement for further binary redistribution.
   17  *
   18  * NO WARRANTY
   19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   21  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
   22  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
   23  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
   24  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
   27  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   29  * THE POSSIBILITY OF SUCH DAMAGES.
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 #ifdef __FreeBSD__
   34 __FBSDID("$FreeBSD: releng/11.1/sys/dev/malo/if_malohal.c 267340 2014-06-10 20:25:45Z jhb $");
   35 #endif
   36 
   37 #include <sys/param.h>
   38 #include <sys/systm.h>
   39 #include <sys/endian.h>
   40 #include <sys/kernel.h>
   41 #include <sys/malloc.h>
   42 #include <sys/firmware.h>
   43 #include <sys/socket.h>
   44 
   45 #include <machine/bus.h>
   46 #include <sys/bus.h>
   47 
   48 #include <net/if.h>
   49 #include <net/if_var.h>
   50 #include <net/if_dl.h>
   51 #include <net/if_media.h>
   52 #include <net/ethernet.h>
   53 
   54 #include <net80211/ieee80211_var.h>
   55 
   56 #include <dev/malo/if_malo.h>
   57 
   58 #define MALO_WAITOK                             1
   59 #define MALO_NOWAIT                             0
   60 
   61 #define _CMD_SETUP(pCmd, _type, _cmd) do {                              \
   62         pCmd = (_type *)&mh->mh_cmdbuf[0];                              \
   63         memset(pCmd, 0, sizeof(_type));                                 \
   64         pCmd->cmdhdr.cmd = htole16(_cmd);                               \
   65         pCmd->cmdhdr.length = htole16(sizeof(_type));                   \
   66 } while (0)
   67 
   68 static __inline uint32_t
   69 malo_hal_read4(struct malo_hal *mh, bus_size_t off)
   70 {
   71         return bus_space_read_4(mh->mh_iot, mh->mh_ioh, off);
   72 }
   73 
   74 static __inline void
   75 malo_hal_write4(struct malo_hal *mh, bus_size_t off, uint32_t val)
   76 {
   77         bus_space_write_4(mh->mh_iot, mh->mh_ioh, off, val);
   78 }
   79 
   80 static void
   81 malo_hal_load_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
   82 {
   83         bus_addr_t *paddr = (bus_addr_t*) arg;
   84 
   85         KASSERT(error == 0, ("error %u on bus_dma callback", error));
   86         *paddr = segs->ds_addr;
   87 }
   88 
   89 /*
   90  * Setup for communication with the device.  We allocate
   91  * a command buffer and map it for bus dma use.  The pci
   92  * device id is used to identify whether the device has
   93  * SRAM on it (in which case f/w download must include a
   94  * memory controller reset).  All bus i/o operations happen
   95  * in BAR 1; the driver passes in the tag and handle we need.
   96  */
   97 struct malo_hal *
   98 malo_hal_attach(device_t dev, uint16_t devid,
   99     bus_space_handle_t ioh, bus_space_tag_t iot, bus_dma_tag_t tag)
  100 {
  101         int error;
  102         struct malo_hal *mh;
  103 
  104         mh = malloc(sizeof(struct malo_hal), M_DEVBUF, M_NOWAIT | M_ZERO);
  105         if (mh == NULL)
  106                 return NULL;
  107 
  108         mh->mh_dev = dev;
  109         mh->mh_ioh = ioh;
  110         mh->mh_iot = iot;
  111 
  112         snprintf(mh->mh_mtxname, sizeof(mh->mh_mtxname),
  113             "%s_hal", device_get_nameunit(dev));
  114         mtx_init(&mh->mh_mtx, mh->mh_mtxname, NULL, MTX_DEF);
  115 
  116         /*
  117          * Allocate the command buffer and map into the address
  118          * space of the h/w.  We request "coherent" memory which
  119          * will be uncached on some architectures.
  120          */
  121         error = bus_dma_tag_create(tag,         /* parent */
  122                        PAGE_SIZE, 0,            /* alignment, bounds */
  123                        BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
  124                        BUS_SPACE_MAXADDR,       /* highaddr */
  125                        NULL, NULL,              /* filter, filterarg */
  126                        MALO_CMDBUF_SIZE,        /* maxsize */
  127                        1,                       /* nsegments */
  128                        MALO_CMDBUF_SIZE,        /* maxsegsize */
  129                        BUS_DMA_ALLOCNOW,        /* flags */
  130                        NULL,                    /* lockfunc */
  131                        NULL,                    /* lockarg */
  132                        &mh->mh_dmat);
  133         if (error != 0) {
  134                 device_printf(dev, "unable to allocate memory for cmd tag, "
  135                         "error %u\n", error);
  136                 goto fail;
  137         }
  138 
  139         /* allocate descriptors */
  140         error = bus_dmamem_alloc(mh->mh_dmat, (void**) &mh->mh_cmdbuf,
  141                                  BUS_DMA_NOWAIT | BUS_DMA_COHERENT, 
  142                                  &mh->mh_dmamap);
  143         if (error != 0) {
  144                 device_printf(dev, "unable to allocate memory for cmd buffer, "
  145                         "error %u\n", error);
  146                 goto fail;
  147         }
  148 
  149         error = bus_dmamap_load(mh->mh_dmat, mh->mh_dmamap,
  150                                 mh->mh_cmdbuf, MALO_CMDBUF_SIZE,
  151                                 malo_hal_load_cb, &mh->mh_cmdaddr,
  152                                 BUS_DMA_NOWAIT);
  153         if (error != 0) {
  154                 device_printf(dev, "unable to load cmd buffer, error %u\n",
  155                         error);
  156                 goto fail;
  157         }
  158 
  159         return (mh);
  160 
  161 fail:
  162         if (mh->mh_cmdbuf != NULL)
  163                 bus_dmamem_free(mh->mh_dmat, mh->mh_cmdbuf,
  164                     mh->mh_dmamap);
  165         if (mh->mh_dmat)
  166                 bus_dma_tag_destroy(mh->mh_dmat);
  167         free(mh, M_DEVBUF);
  168 
  169         return (NULL);
  170 }
  171 
  172 /*
  173  * Low level firmware cmd block handshake support.
  174  */
  175 
  176 static void
  177 malo_hal_send_cmd(struct malo_hal *mh)
  178 {
  179         uint32_t dummy;
  180 
  181         bus_dmamap_sync(mh->mh_dmat, mh->mh_dmamap,
  182             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
  183 
  184         malo_hal_write4(mh, MALO_REG_GEN_PTR, mh->mh_cmdaddr);
  185         dummy = malo_hal_read4(mh, MALO_REG_INT_CODE);
  186 
  187         malo_hal_write4(mh, MALO_REG_H2A_INTERRUPT_EVENTS,
  188             MALO_H2ARIC_BIT_DOOR_BELL);
  189 }
  190 
  191 static int
  192 malo_hal_waitforcmd(struct malo_hal *mh, uint16_t cmd)
  193 {
  194 #define MAX_WAIT_FW_COMPLETE_ITERATIONS 10000
  195         int i;
  196 
  197         for (i = 0; i < MAX_WAIT_FW_COMPLETE_ITERATIONS; i++) {
  198                 if (mh->mh_cmdbuf[0] == le16toh(cmd))
  199                         return 1;
  200 
  201                 DELAY(1 * 1000);
  202         }
  203 
  204         return 0;
  205 #undef MAX_WAIT_FW_COMPLETE_ITERATIONS
  206 }
  207 
  208 static int
  209 malo_hal_execute_cmd(struct malo_hal *mh, unsigned short cmd)
  210 {
  211         MALO_HAL_LOCK_ASSERT(mh);
  212 
  213         if ((mh->mh_flags & MHF_FWHANG) &&
  214             (mh->mh_debug & MALO_HAL_DEBUG_IGNHANG) == 0) {
  215                 device_printf(mh->mh_dev, "firmware hung, skipping cmd 0x%x\n",
  216                         cmd);
  217                 return ENXIO;
  218         }
  219 
  220         if (malo_hal_read4(mh, MALO_REG_INT_CODE) == 0xffffffff) {
  221                 device_printf(mh->mh_dev, "%s: device not present!\n",
  222                     __func__);
  223                 return EIO;
  224         }
  225 
  226         malo_hal_send_cmd(mh);
  227         if (!malo_hal_waitforcmd(mh, cmd | 0x8000)) {
  228                 device_printf(mh->mh_dev,
  229                     "timeout waiting for f/w cmd 0x%x\n", cmd);
  230                 mh->mh_flags |= MHF_FWHANG;
  231                 return ETIMEDOUT;
  232         }
  233 
  234         bus_dmamap_sync(mh->mh_dmat, mh->mh_dmamap,
  235             BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
  236 
  237         return 0;
  238 }
  239 
  240 static int
  241 malo_hal_get_cal_table(struct malo_hal *mh, uint8_t annex, uint8_t index)
  242 {
  243         struct malo_cmd_caltable *cmd;
  244         int ret;
  245 
  246         MALO_HAL_LOCK_ASSERT(mh);
  247 
  248         _CMD_SETUP(cmd, struct malo_cmd_caltable, MALO_HOSTCMD_GET_CALTABLE);
  249         cmd->annex = annex;
  250         cmd->index = index;
  251 
  252         ret = malo_hal_execute_cmd(mh, MALO_HOSTCMD_GET_CALTABLE);
  253         if (ret == 0 && cmd->caltbl[0] != annex && annex != 0 && annex != 255)
  254                 ret = EIO;
  255         return ret;
  256 }                                                         
  257 
  258 static int
  259 malo_hal_get_pwrcal_table(struct malo_hal *mh, struct malo_hal_caldata *cal)
  260 {
  261         const uint8_t *data;
  262         int len;
  263 
  264         MALO_HAL_LOCK(mh);
  265         /* NB: we hold the lock so it's ok to use cmdbuf */
  266         data = ((const struct malo_cmd_caltable *) mh->mh_cmdbuf)->caltbl;
  267         if (malo_hal_get_cal_table(mh, 33, 0) == 0) {
  268                 len = (data[2] | (data[3] << 8)) - 12;
  269                 /* XXX validate len */
  270                 memcpy(cal->pt_ratetable_20m, &data[12], len);  
  271         }
  272         mh->mh_flags |= MHF_CALDATA;
  273         MALO_HAL_UNLOCK(mh);
  274 
  275         return 0;
  276 }
  277 
  278 /*
  279  * Reset internal state after a firmware download.
  280  */
  281 static int
  282 malo_hal_resetstate(struct malo_hal *mh)
  283 {
  284         /*
  285          * Fetch cal data for later use.
  286          * XXX may want to fetch other stuff too.
  287          */
  288         if ((mh->mh_flags & MHF_CALDATA) == 0)
  289                 malo_hal_get_pwrcal_table(mh, &mh->mh_caldata);
  290         return 0;
  291 }
  292 
  293 static void
  294 malo_hal_fw_reset(struct malo_hal *mh)
  295 {
  296 
  297         if (malo_hal_read4(mh,  MALO_REG_INT_CODE) == 0xffffffff) {
  298                 device_printf(mh->mh_dev, "%s: device not present!\n",
  299                     __func__);
  300                 return;
  301         }
  302 
  303         malo_hal_write4(mh, MALO_REG_H2A_INTERRUPT_EVENTS, MALO_ISR_RESET);
  304         mh->mh_flags &= ~MHF_FWHANG;
  305 }
  306 
  307 static void
  308 malo_hal_trigger_pcicmd(struct malo_hal *mh)
  309 {
  310         uint32_t dummy;
  311 
  312         bus_dmamap_sync(mh->mh_dmat, mh->mh_dmamap, BUS_DMASYNC_PREWRITE);
  313 
  314         malo_hal_write4(mh, MALO_REG_GEN_PTR, mh->mh_cmdaddr);
  315         dummy = malo_hal_read4(mh, MALO_REG_INT_CODE);
  316 
  317         malo_hal_write4(mh, MALO_REG_INT_CODE, 0x00);
  318         dummy = malo_hal_read4(mh, MALO_REG_INT_CODE);
  319 
  320         malo_hal_write4(mh, MALO_REG_H2A_INTERRUPT_EVENTS,
  321             MALO_H2ARIC_BIT_DOOR_BELL);
  322         dummy = malo_hal_read4(mh, MALO_REG_INT_CODE);
  323 }
  324 
  325 static int
  326 malo_hal_waitfor(struct malo_hal *mh, uint32_t val)
  327 {
  328         int i;
  329 
  330         for (i = 0; i < MALO_FW_MAX_NUM_CHECKS; i++) {
  331                 DELAY(MALO_FW_CHECK_USECS);
  332                 if (malo_hal_read4(mh, MALO_REG_INT_CODE) == val)
  333                         return 0;
  334         }
  335 
  336         return -1;
  337 }
  338 
  339 /*
  340  * Firmware block xmit when talking to the boot-rom.
  341  */
  342 static int
  343 malo_hal_send_helper(struct malo_hal *mh, int bsize,
  344     const void *data, size_t dsize, int waitfor)
  345 {
  346         mh->mh_cmdbuf[0] = htole16(MALO_HOSTCMD_CODE_DNLD);
  347         mh->mh_cmdbuf[1] = htole16(bsize);
  348         memcpy(&mh->mh_cmdbuf[4], data , dsize);
  349 
  350         malo_hal_trigger_pcicmd(mh);
  351 
  352         if (waitfor == MALO_NOWAIT)
  353                 goto pass;
  354 
  355         /* XXX 2000 vs 200 */
  356         if (malo_hal_waitfor(mh, MALO_INT_CODE_CMD_FINISHED) != 0) {
  357                 device_printf(mh->mh_dev,
  358                     "%s: timeout waiting for CMD_FINISHED, INT_CODE 0x%x\n",
  359                     __func__, malo_hal_read4(mh, MALO_REG_INT_CODE));
  360                 
  361                 return ETIMEDOUT;
  362         }
  363 
  364 pass:
  365         malo_hal_write4(mh, MALO_REG_INT_CODE, 0);
  366 
  367         return (0);
  368 }
  369 
  370 static int
  371 malo_hal_fwload_helper(struct malo_hal *mh, char *helper)
  372 {
  373         const struct firmware *fw;
  374         int error;
  375 
  376         fw = firmware_get(helper);
  377         if (fw == NULL) {
  378                 device_printf(mh->mh_dev, "could not read microcode %s!\n",
  379                     helper);
  380                 return (EIO);
  381         }
  382 
  383         device_printf(mh->mh_dev, "load %s firmware image (%zu bytes)\n",
  384             helper, fw->datasize);
  385 
  386         error = malo_hal_send_helper(mh, fw->datasize, fw->data, fw->datasize,
  387                 MALO_WAITOK);
  388         if (error != 0)
  389                 goto fail;
  390 
  391         /* tell the card we're done and... */
  392         error = malo_hal_send_helper(mh, 0, NULL, 0, MALO_NOWAIT);
  393 
  394 fail:
  395         firmware_put(fw, FIRMWARE_UNLOAD);
  396 
  397         return (error);
  398 }
  399 
  400 /*
  401  * Firmware block xmit when talking to the 1st-stage loader.
  402  */
  403 static int
  404 malo_hal_send_main(struct malo_hal *mh, const void *data, size_t dsize,
  405     uint16_t seqnum, int waitfor)
  406 {
  407         mh->mh_cmdbuf[0] = htole16(MALO_HOSTCMD_CODE_DNLD);
  408         mh->mh_cmdbuf[1] = htole16(dsize);
  409         mh->mh_cmdbuf[2] = htole16(seqnum);
  410         mh->mh_cmdbuf[3] = 0;
  411         memcpy(&mh->mh_cmdbuf[4], data, dsize);
  412 
  413         malo_hal_trigger_pcicmd(mh);
  414 
  415         if (waitfor == MALO_NOWAIT)
  416                 goto pass;
  417 
  418         if (malo_hal_waitfor(mh, MALO_INT_CODE_CMD_FINISHED) != 0) {
  419                 device_printf(mh->mh_dev,
  420                     "%s: timeout waiting for CMD_FINISHED, INT_CODE 0x%x\n",
  421                     __func__, malo_hal_read4(mh, MALO_REG_INT_CODE));
  422 
  423                 return ETIMEDOUT;
  424         }
  425 
  426 pass:
  427         malo_hal_write4(mh, MALO_REG_INT_CODE, 0);
  428 
  429         return 0;
  430 }
  431 
  432 static int
  433 malo_hal_fwload_main(struct malo_hal *mh, char *firmware)
  434 {
  435         const struct firmware *fw;
  436         const uint8_t *fp;
  437         int error;
  438         size_t count;
  439         uint16_t seqnum;
  440         uint32_t blocksize;
  441 
  442         error = 0;
  443 
  444         fw = firmware_get(firmware);
  445         if (fw == NULL) {
  446                 device_printf(mh->mh_dev, "could not read firmware %s!\n",
  447                     firmware);
  448                 return (EIO);
  449         }
  450 
  451         device_printf(mh->mh_dev, "load %s firmware image (%zu bytes)\n",
  452             firmware, fw->datasize);
  453 
  454         seqnum = 1;
  455         for (count = 0; count < fw->datasize; count += blocksize) {
  456                 blocksize = MIN(256, fw->datasize - count);
  457                 fp = (const uint8_t *)fw->data + count;
  458 
  459                 error = malo_hal_send_main(mh, fp, blocksize, seqnum++,
  460                     MALO_NOWAIT);
  461                 if (error != 0)
  462                         goto fail;
  463                 DELAY(500);
  464         }
  465         
  466         /*
  467          * send a command with size 0 to tell that the firmware has been
  468          * uploaded
  469          */
  470         error = malo_hal_send_main(mh, NULL, 0, seqnum++, MALO_NOWAIT);
  471         DELAY(100);
  472 
  473 fail:
  474         firmware_put(fw, FIRMWARE_UNLOAD);
  475 
  476         return (error);
  477 }
  478 
  479 int
  480 malo_hal_fwload(struct malo_hal *mh, char *helper, char *firmware)
  481 {
  482         int error, i;
  483         uint32_t fwreadysig, opmode;
  484 
  485         /*
  486          * NB: now malo(4) supports only STA mode.  It will be better if it
  487          * supports AP mode.
  488          */
  489         fwreadysig = MALO_HOSTCMD_STA_FWRDY_SIGNATURE;
  490         opmode = MALO_HOSTCMD_STA_MODE;
  491 
  492         malo_hal_fw_reset(mh);
  493 
  494         malo_hal_write4(mh, MALO_REG_A2H_INTERRUPT_CLEAR_SEL,
  495             MALO_A2HRIC_BIT_MASK);
  496         malo_hal_write4(mh, MALO_REG_A2H_INTERRUPT_CAUSE, 0x00);
  497         malo_hal_write4(mh, MALO_REG_A2H_INTERRUPT_MASK, 0x00);
  498         malo_hal_write4(mh, MALO_REG_A2H_INTERRUPT_STATUS_MASK,
  499             MALO_A2HRIC_BIT_MASK);
  500 
  501         error = malo_hal_fwload_helper(mh, helper);
  502         if (error != 0) {
  503                 device_printf(mh->mh_dev, "failed to load bootrom loader.\n");
  504                 goto fail;
  505         }
  506 
  507         DELAY(200 * MALO_FW_CHECK_USECS);
  508 
  509         error = malo_hal_fwload_main(mh, firmware);
  510         if (error != 0) {
  511                 device_printf(mh->mh_dev, "failed to load firmware.\n");
  512                 goto fail;
  513         }
  514 
  515         /*
  516          * Wait for firmware to startup; we monitor the INT_CODE register
  517          * waiting for a signature to written back indicating it's ready to go.
  518          */
  519         mh->mh_cmdbuf[1] = 0;
  520 
  521         if (opmode != MALO_HOSTCMD_STA_MODE)
  522                 malo_hal_trigger_pcicmd(mh);
  523         
  524         for (i = 0; i < MALO_FW_MAX_NUM_CHECKS; i++) {
  525                 malo_hal_write4(mh, MALO_REG_GEN_PTR, opmode);
  526                 DELAY(MALO_FW_CHECK_USECS);
  527                 if (malo_hal_read4(mh, MALO_REG_INT_CODE) == fwreadysig) {
  528                         malo_hal_write4(mh, MALO_REG_INT_CODE, 0x00);
  529                         return malo_hal_resetstate(mh);
  530                 }
  531         }
  532 
  533         return ETIMEDOUT;
  534 fail:
  535         malo_hal_fw_reset(mh);
  536 
  537         return (error);
  538 }
  539 
  540 /*
  541  * Return "hw specs".  Note this must be the first cmd MUST be done after
  542  * a firmware download or the f/w will lockup.
  543  */
  544 int
  545 malo_hal_gethwspecs(struct malo_hal *mh, struct malo_hal_hwspec *hw)
  546 {
  547         struct malo_cmd_get_hwspec *cmd;
  548         int ret;
  549 
  550         MALO_HAL_LOCK(mh);
  551 
  552         _CMD_SETUP(cmd, struct malo_cmd_get_hwspec, MALO_HOSTCMD_GET_HW_SPEC);
  553         memset(&cmd->permaddr[0], 0xff, IEEE80211_ADDR_LEN);
  554         cmd->ul_fw_awakecookie = htole32((unsigned int)mh->mh_cmdaddr + 2048);
  555 
  556         ret = malo_hal_execute_cmd(mh, MALO_HOSTCMD_GET_HW_SPEC);
  557         if (ret == 0) {
  558                 IEEE80211_ADDR_COPY(hw->macaddr, cmd->permaddr);
  559                 hw->wcbbase[0] = le32toh(cmd->wcbbase0) & 0x0000ffff;
  560                 hw->wcbbase[1] = le32toh(cmd->wcbbase1) & 0x0000ffff;
  561                 hw->wcbbase[2] = le32toh(cmd->wcbbase2) & 0x0000ffff;
  562                 hw->wcbbase[3] = le32toh(cmd->wcbbase3) & 0x0000ffff;
  563                 hw->rxdesc_read = le32toh(cmd->rxpdrd_ptr)& 0x0000ffff;
  564                 hw->rxdesc_write = le32toh(cmd->rxpdwr_ptr)& 0x0000ffff;
  565                 hw->regioncode = le16toh(cmd->regioncode) & 0x00ff;
  566                 hw->fw_releasenum = le32toh(cmd->fw_releasenum);
  567                 hw->maxnum_wcb = le16toh(cmd->num_wcb);
  568                 hw->maxnum_mcaddr = le16toh(cmd->num_mcastaddr);
  569                 hw->num_antenna = le16toh(cmd->num_antenna);
  570                 hw->hwversion = cmd->version;
  571                 hw->hostinterface = cmd->hostif;
  572         }
  573 
  574         MALO_HAL_UNLOCK(mh);
  575 
  576         return ret;
  577 }
  578 
  579 void
  580 malo_hal_detach(struct malo_hal *mh)
  581 {
  582 
  583         bus_dmamem_free(mh->mh_dmat, mh->mh_cmdbuf, mh->mh_dmamap);
  584         bus_dma_tag_destroy(mh->mh_dmat);
  585         mtx_destroy(&mh->mh_mtx);
  586         free(mh, M_DEVBUF);
  587 }
  588 
  589 /*
  590  * Configure antenna use.  Takes effect immediately.
  591  *
  592  * XXX tx antenna setting ignored
  593  * XXX rx antenna setting should always be 3 (for now)
  594  */
  595 int
  596 malo_hal_setantenna(struct malo_hal *mh, enum malo_hal_antenna dirset, int ant)
  597 {
  598         struct malo_cmd_rf_antenna *cmd;
  599         int ret;
  600 
  601         if (!(dirset == MHA_ANTENNATYPE_RX || dirset == MHA_ANTENNATYPE_TX))
  602                 return EINVAL;
  603 
  604         MALO_HAL_LOCK(mh);
  605 
  606         _CMD_SETUP(cmd, struct malo_cmd_rf_antenna,
  607             MALO_HOSTCMD_802_11_RF_ANTENNA);
  608         cmd->action = htole16(dirset);
  609         if (ant == 0) {                 /* default to all/both antennae */
  610                 /* XXX never reach now.  */
  611                 ant = 3;
  612         }
  613         cmd->mode = htole16(ant);
  614 
  615         ret = malo_hal_execute_cmd(mh, MALO_HOSTCMD_802_11_RF_ANTENNA);
  616 
  617         MALO_HAL_UNLOCK(mh);
  618 
  619         return ret;
  620 }
  621 
  622 /*
  623  * Configure radio.  Takes effect immediately.
  624  *
  625  * XXX preamble installed after set fixed rate cmd
  626  */
  627 int
  628 malo_hal_setradio(struct malo_hal *mh, int onoff,
  629     enum malo_hal_preamble preamble)
  630 {
  631         struct malo_cmd_radio_control *cmd;
  632         int ret;
  633 
  634         MALO_HAL_LOCK(mh);
  635 
  636         _CMD_SETUP(cmd, struct malo_cmd_radio_control,
  637             MALO_HOSTCMD_802_11_RADIO_CONTROL);
  638         cmd->action = htole16(MALO_HOSTCMD_ACT_GEN_SET);
  639         if (onoff == 0)
  640                 cmd->control = 0;
  641         else
  642                 cmd->control = htole16(preamble);
  643         cmd->radio_on = htole16(onoff);
  644 
  645         ret = malo_hal_execute_cmd(mh, MALO_HOSTCMD_802_11_RADIO_CONTROL);
  646 
  647         MALO_HAL_UNLOCK(mh);
  648 
  649         return ret;
  650 }
  651 
  652 /*
  653  * Set the interrupt mask.
  654  */
  655 void
  656 malo_hal_intrset(struct malo_hal *mh, uint32_t mask)
  657 {
  658 
  659         malo_hal_write4(mh, MALO_REG_A2H_INTERRUPT_MASK, 0);
  660         (void)malo_hal_read4(mh, MALO_REG_INT_CODE);
  661 
  662         mh->mh_imask = mask;
  663         malo_hal_write4(mh, MALO_REG_A2H_INTERRUPT_MASK, mask);
  664         (void)malo_hal_read4(mh, MALO_REG_INT_CODE);
  665 }
  666 
  667 int
  668 malo_hal_setchannel(struct malo_hal *mh, const struct malo_hal_channel *chan)
  669 {
  670         struct malo_cmd_fw_set_rf_channel *cmd;
  671         int ret;
  672 
  673         MALO_HAL_LOCK(mh);
  674 
  675         _CMD_SETUP(cmd, struct malo_cmd_fw_set_rf_channel,
  676             MALO_HOSTCMD_SET_RF_CHANNEL);
  677         cmd->action = htole16(MALO_HOSTCMD_ACT_GEN_SET);
  678         cmd->cur_channel = chan->channel;
  679 
  680         ret = malo_hal_execute_cmd(mh, MALO_HOSTCMD_SET_RF_CHANNEL);
  681 
  682         MALO_HAL_UNLOCK(mh);
  683 
  684         return ret;
  685 }
  686 
  687 int
  688 malo_hal_settxpower(struct malo_hal *mh, const struct malo_hal_channel *c)
  689 {
  690         struct malo_cmd_rf_tx_power *cmd;
  691         const struct malo_hal_caldata *cal = &mh->mh_caldata;
  692         uint8_t chan = c->channel;
  693         uint16_t pow;
  694         int i, idx, ret;
  695         
  696         MALO_HAL_LOCK(mh);
  697 
  698         _CMD_SETUP(cmd, struct malo_cmd_rf_tx_power,
  699             MALO_HOSTCMD_802_11_RF_TX_POWER);
  700         cmd->action = htole16(MALO_HOSTCMD_ACT_GEN_SET_LIST);
  701         for (i = 0; i < 4; i++) {
  702                 idx = (chan - 1) * 4 + i;
  703                 pow = cal->pt_ratetable_20m[idx];
  704                 cmd->power_levellist[i] = htole16(pow);
  705         }
  706         ret = malo_hal_execute_cmd(mh, MALO_HOSTCMD_802_11_RF_TX_POWER);
  707 
  708         MALO_HAL_UNLOCK(mh);
  709 
  710         return ret;
  711 }
  712 
  713 int
  714 malo_hal_setpromisc(struct malo_hal *mh, int enable)
  715 {
  716         /* XXX need host cmd */
  717         return 0;
  718 }
  719 
  720 int
  721 malo_hal_setassocid(struct malo_hal *mh,
  722     const uint8_t bssid[IEEE80211_ADDR_LEN], uint16_t associd)
  723 {
  724         struct malo_cmd_fw_set_aid *cmd;
  725         int ret;
  726 
  727         MALO_HAL_LOCK(mh);
  728 
  729         _CMD_SETUP(cmd, struct malo_cmd_fw_set_aid,
  730             MALO_HOSTCMD_SET_AID);
  731         cmd->cmdhdr.seqnum = 1;
  732         cmd->associd = htole16(associd);
  733         IEEE80211_ADDR_COPY(&cmd->macaddr[0], bssid);
  734         
  735         ret = malo_hal_execute_cmd(mh, MALO_HOSTCMD_SET_AID);
  736         MALO_HAL_UNLOCK(mh);
  737         return ret;
  738 }
  739 
  740 /*
  741  * Kick the firmware to tell it there are new tx descriptors
  742  * for processing.  The driver says what h/w q has work in
  743  * case the f/w ever gets smarter.
  744  */
  745 void
  746 malo_hal_txstart(struct malo_hal *mh, int qnum)
  747 {
  748         bus_space_write_4(mh->mh_iot, mh->mh_ioh,
  749             MALO_REG_H2A_INTERRUPT_EVENTS, MALO_H2ARIC_BIT_PPA_READY);
  750         (void) bus_space_read_4(mh->mh_iot, mh->mh_ioh, MALO_REG_INT_CODE);
  751 }
  752 
  753 /*
  754  * Return the current ISR setting and clear the cause.
  755  */
  756 void
  757 malo_hal_getisr(struct malo_hal *mh, uint32_t *status)
  758 {
  759         uint32_t cause;
  760 
  761         cause = bus_space_read_4(mh->mh_iot, mh->mh_ioh,
  762             MALO_REG_A2H_INTERRUPT_CAUSE);
  763         if (cause == 0xffffffff) {      /* card removed */
  764                 cause = 0;
  765         } else if (cause != 0) {
  766                 /* clear cause bits */
  767                 bus_space_write_4(mh->mh_iot, mh->mh_ioh,
  768                     MALO_REG_A2H_INTERRUPT_CAUSE, cause &~ mh->mh_imask);
  769                 (void) bus_space_read_4(mh->mh_iot, mh->mh_ioh,
  770                     MALO_REG_INT_CODE);
  771                 cause &= mh->mh_imask;
  772         }
  773 
  774         *status = cause;
  775 }
  776 
  777 /*
  778  * Callback from the driver on a cmd done interrupt.  Nothing to do right
  779  * now as we spin waiting for cmd completion.
  780  */
  781 void
  782 malo_hal_cmddone(struct malo_hal *mh)
  783 {
  784         /* NB : do nothing.  */
  785 }
  786 
  787 int
  788 malo_hal_prescan(struct malo_hal *mh)
  789 {
  790         struct malo_cmd_prescan *cmd;
  791         int ret;
  792 
  793         MALO_HAL_LOCK(mh);
  794 
  795         _CMD_SETUP(cmd, struct malo_cmd_prescan, MALO_HOSTCMD_SET_PRE_SCAN);
  796         cmd->cmdhdr.seqnum = 1;
  797         
  798         ret = malo_hal_execute_cmd(mh, MALO_HOSTCMD_SET_PRE_SCAN);
  799 
  800         MALO_HAL_UNLOCK(mh);
  801 
  802         return ret;
  803 }
  804 
  805 int
  806 malo_hal_postscan(struct malo_hal *mh, uint8_t *macaddr, uint8_t ibsson)
  807 {
  808         struct malo_cmd_postscan *cmd;
  809         int ret;
  810 
  811         MALO_HAL_LOCK(mh);
  812 
  813         _CMD_SETUP(cmd, struct malo_cmd_postscan, MALO_HOSTCMD_SET_POST_SCAN);
  814         cmd->cmdhdr.seqnum = 1;
  815         cmd->isibss = htole32(ibsson);
  816         IEEE80211_ADDR_COPY(&cmd->bssid[0], macaddr);
  817 
  818         ret = malo_hal_execute_cmd(mh, MALO_HOSTCMD_SET_POST_SCAN);
  819 
  820         MALO_HAL_UNLOCK(mh);
  821 
  822         return ret;
  823 }
  824 
  825 int
  826 malo_hal_set_slot(struct malo_hal *mh, int is_short)
  827 {
  828         int ret;
  829         struct malo_cmd_fw_setslot *cmd;
  830 
  831         MALO_HAL_LOCK(mh);
  832 
  833         _CMD_SETUP(cmd, struct malo_cmd_fw_setslot, MALO_HOSTCMD_SET_SLOT);
  834         cmd->action = htole16(MALO_HOSTCMD_ACT_GEN_SET);
  835         cmd->slot = (is_short == 1 ? 1 : 0);
  836 
  837         ret = malo_hal_execute_cmd(mh, MALO_HOSTCMD_SET_SLOT);
  838 
  839         MALO_HAL_UNLOCK(mh);
  840 
  841         return ret;
  842 }
  843 
  844 int
  845 malo_hal_set_rate(struct malo_hal *mh, uint16_t curmode, uint8_t rate)
  846 {
  847         int i, ret;
  848         struct malo_cmd_set_rate *cmd;
  849 
  850         MALO_HAL_LOCK(mh);
  851 
  852         _CMD_SETUP(cmd, struct malo_cmd_set_rate, MALO_HOSTCMD_SET_RATE);
  853         cmd->aprates[0] = 2;
  854         cmd->aprates[1] = 4;
  855         cmd->aprates[2] = 11;
  856         cmd->aprates[3] = 22;
  857         if (curmode == IEEE80211_MODE_11G) {
  858                 cmd->aprates[4] = 0;            /* XXX reserved?  */
  859                 cmd->aprates[5] = 12;
  860                 cmd->aprates[6] = 18;
  861                 cmd->aprates[7] = 24;
  862                 cmd->aprates[8] = 36;
  863                 cmd->aprates[9] = 48;
  864                 cmd->aprates[10] = 72;
  865                 cmd->aprates[11] = 96;
  866                 cmd->aprates[12] = 108;
  867         }
  868 
  869         if (rate != 0) {
  870                 /* fixed rate */
  871                 for (i = 0; i < 13; i++) {
  872                         if (cmd->aprates[i] == rate) {
  873                                 cmd->rateindex = i;
  874                                 cmd->dataratetype = 1;
  875                                 break;
  876                         }
  877                 }
  878         }
  879 
  880         ret = malo_hal_execute_cmd(mh, MALO_HOSTCMD_SET_RATE);
  881 
  882         MALO_HAL_UNLOCK(mh);
  883 
  884         return ret;
  885 }
  886 
  887 int
  888 malo_hal_setmcast(struct malo_hal *mh, int nmc, const uint8_t macs[])
  889 {
  890         struct malo_cmd_mcast *cmd;
  891         int ret;
  892 
  893         if (nmc > MALO_HAL_MCAST_MAX)
  894                 return EINVAL;
  895 
  896         MALO_HAL_LOCK(mh);
  897 
  898         _CMD_SETUP(cmd, struct malo_cmd_mcast, MALO_HOSTCMD_MAC_MULTICAST_ADR);
  899         memcpy(cmd->maclist, macs, nmc * IEEE80211_ADDR_LEN);
  900         cmd->numaddr = htole16(nmc);
  901         cmd->action = htole16(0xffff);
  902 
  903         ret = malo_hal_execute_cmd(mh, MALO_HOSTCMD_MAC_MULTICAST_ADR);
  904 
  905         MALO_HAL_UNLOCK(mh);
  906 
  907         return ret;
  908 }

Cache object: c743c0b2c5d5f9ddc39e3a30c1909164


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.