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

Cache object: 01d027c88f3802d025bd0362e12c39c0


[ 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.