Exemple #1
0
static bool
dbus_usb_dlneeded(void *bus)
{
	usb_info_t *usbinfo = BUS_INFO(bus, usb_info_t);
	void *osinfo;
	bootrom_id_t id;
	bool dl_needed = TRUE;

	DBUSTRACE(("%s\n", __FUNCTION__));

	if (usbinfo == NULL)
		return FALSE;

	osinfo = usbinfo->usbosl_info;
	ASSERT(osinfo);

	/* Check if firmware downloaded already by querying runtime ID */
	id.chip = 0xDEAD;
	dbus_usbos_dl_cmd(osinfo, DL_GETVER, &id, sizeof(bootrom_id_t));

	id.chip = ltoh32(id.chip);
	id.chiprev = ltoh32(id.chiprev);

	if (FALSE == dbus_usb_update_chipinfo(usbinfo, id.chip)) {
		dl_needed = FALSE;
		goto exit;
	}

	DBUSERR(("%s: chip 0x%x rev 0x%x\n", __FUNCTION__, id.chip, id.chiprev));
	if (id.chip == POSTBOOT_ID) {
		/* This code is  needed to support two enumerations on USB1.1 scenario */
		DBUSERR(("%s: Firmware already downloaded\n", __FUNCTION__));

		dbus_usbos_dl_cmd(osinfo, DL_RESETCFG, &id, sizeof(bootrom_id_t));
		dl_needed = FALSE;
		if (usbinfo->pub->busstate == DBUS_STATE_DL_PENDING)
			usbinfo->pub->busstate = DBUS_STATE_DL_DONE;
	} else {
		usbinfo->pub->attrib.devid = id.chip;
		usbinfo->pub->attrib.chiprev = id.chiprev;
	}

exit:
	return dl_needed;
}
Exemple #2
0
static int
dbus_usb_dlrun(void *bus)
{
	usb_info_t *usbinfo = BUS_INFO(bus, usb_info_t);
	void *osinfo;
	rdl_state_t state;
	int err = DBUS_OK;

	DBUSTRACE(("%s\n", __FUNCTION__));

	if (usbinfo == NULL)
		return DBUS_ERR;

	if (USB_DEV_ISBAD(usbinfo))
		return DBUS_ERR;

	osinfo = usbinfo->usbosl_info;
	ASSERT(osinfo);

	/* Check we are runnable */
	dbus_usbos_dl_cmd(osinfo, DL_GETSTATE, &state, sizeof(rdl_state_t));

	state.state = ltoh32(state.state);
	state.bytes = ltoh32(state.bytes);

	/* Start the image */
	if (state.state == DL_RUNNABLE) {
		DBUSERR(("%s: Issue DL_GO\n", __FUNCTION__));
		dbus_usbos_dl_cmd(osinfo, DL_GO, &state, sizeof(rdl_state_t));

		/* FIX: Need this for 4326 for some reason
		 * Same issue under both Linux/Windows
		 */
		if (usbinfo->pub->attrib.devid == TEST_CHIP)
			dbus_usbos_wait(osinfo, USB_DLGO_SPINWAIT);

		err = dbus_usb_resetcfg(usbinfo);
	} else {
		DBUSERR(("%s: Dongle not runnable\n", __FUNCTION__));
		err = DBUS_ERR;
	}

	return err;
}
Exemple #3
0
static int
dbus_usb_dlstart(void *bus, uint8 *fw, int len)
{
	usb_info_t *usbinfo = BUS_INFO(bus, usb_info_t);
	int err;

	DBUSTRACE(("%s\n", __FUNCTION__));

	if (usbinfo == NULL)
		return DBUS_ERR;

	if (USB_DEV_ISBAD(usbinfo))
		return DBUS_ERR;

	err = dbus_usb_dl_writeimage(usbinfo, fw, len);
	if (err == DBUS_OK)
		usbinfo->pub->busstate = DBUS_STATE_DL_DONE;
	else
		usbinfo->pub->busstate = DBUS_STATE_DL_PENDING;

	return err;
}
static int
dbus_usb_dl_writeimage(usb_info_t *usbinfo, uint8 *fw, int fwlen)
{
    osl_t *osh = usbinfo->pub->osh;
    void *osinfo = usbinfo->usbosl_info;
    unsigned int sendlen, sent, dllen;
    char *bulkchunk = NULL, *dlpos;
    rdl_state_t state;
    int err = DBUS_OK;
    bootrom_id_t id;
    uint16 wait, wait_time;

    bulkchunk = MALLOC(osh, RDL_CHUNK);
    if (bulkchunk == NULL) {
        err = DBUS_ERR;
        goto fail;
    }

    sent = 0;
    dlpos = fw;
    dllen = fwlen;

    /* Get chip id and rev */
    id.chip = usbinfo->pub->attrib.devid;
    id.chiprev = usbinfo->pub->attrib.chiprev;

    DBUSTRACE(("enter %s: fwlen=%d\n", __FUNCTION__, fwlen));

    dbus_usbos_dl_cmd(osinfo, DL_GETSTATE, &state, sizeof(rdl_state_t));

    /* 3) Load the image */
    while ((sent < dllen)) {
        /* Wait until the usb device reports it received all the bytes we sent */

        if (sent < dllen) {
            if ((dllen-sent) < RDL_CHUNK)
                sendlen = dllen-sent;
            else
                sendlen = RDL_CHUNK;

            /* simply avoid having to send a ZLP by ensuring we never have an even
             * multiple of 64
             */
            if (!(sendlen % 64))
                sendlen -= 4;

            /* send data */
            memcpy(bulkchunk, dlpos, sendlen);
            if (!dbus_usbos_dl_send_bulk(osinfo, bulkchunk, sendlen)) {
                err = DBUS_ERR;
                goto fail;
            }

            dlpos += sendlen;
            sent += sendlen;
            DBUSTRACE(("%s: sendlen %d\n", __FUNCTION__, sendlen));
        }

        /* 43236a0 bootloader runs from sflash, which is slower than rom
         * Wait for downloaded image crc check to complete in the dongle
         */
        wait = 0;
        wait_time = USB_SFLASH_DLIMAGE_SPINWAIT;
        while (!dbus_usbos_dl_cmd(osinfo, DL_GETSTATE, &state,
                                  sizeof(rdl_state_t))) {
            if ((id.chip == 43236) && (id.chiprev == 0)) {
                DBUSERR(("%s: 43236a0 SFlash delay, waiting for dongle crc check "
                         "completion!!!\n", __FUNCTION__));
                dbus_usbos_wait(osinfo, wait_time);
                wait += wait_time;
                if (wait >= USB_SFLASH_DLIMAGE_LIMIT) {
                    DBUSERR(("%s: DL_GETSTATE Failed xxxx\n", __FUNCTION__));
                    err = DBUS_ERR;
                    goto fail;
                    break;
                }
            } else {
                DBUSERR(("%s: DL_GETSTATE Failed xxxx\n", __FUNCTION__));
                err = DBUS_ERR;
                goto fail;
            }
        }

        state.state = ltoh32(state.state);
        state.bytes = ltoh32(state.bytes);

        /* restart if an error is reported */
        if ((state.state == DL_BAD_HDR) || (state.state == DL_BAD_CRC)) {
            DBUSERR(("%s: Bad Hdr or Bad CRC state %d\n", __FUNCTION__, state.state));
            err = DBUS_ERR;
            goto fail;
        }

    }
fail:
    if (bulkchunk)
        MFREE(osh, bulkchunk, RDL_CHUNK);

    return err;
}
static int
dbus_usb_doiovar(usb_info_t *bus, const bcm_iovar_t *vi, uint32 actionid, const char *name,
                 void *params, int plen, void *arg, int len, int val_size)
{
    int bcmerror = 0;
    int32 int_val = 0;
    bool bool_val = 0;

    DBUSTRACE(("%s: Enter, action %d name %s params %p plen %d arg %p len %d val_size %d\n",
               __FUNCTION__, actionid, name, params, plen, arg, len, val_size));

    if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid))) != 0)
        goto exit;

    if (plen >= (int)sizeof(int_val))
        bcopy(params, &int_val, sizeof(int_val));

    bool_val = (int_val != 0) ? TRUE : FALSE;

    switch (actionid) {

    case IOV_SVAL(IOV_MEMBYTES):
    case IOV_GVAL(IOV_MEMBYTES):
    {
        uint32 address;
        uint size, dsize;
        uint8 *data;

        bool set = (actionid == IOV_SVAL(IOV_MEMBYTES));

        ASSERT(plen >= 2*sizeof(int));

        address = (uint32)int_val;
        bcopy((char *)params + sizeof(int_val), &int_val, sizeof(int_val));
        size = (uint)int_val;

        /* Do some validation */
        dsize = set ? plen - (2 * sizeof(int)) : len;
        if (dsize < size) {
            DBUSTRACE(("%s: error on %s membytes, addr 0x%08x size %d dsize %d\n",
                       __FUNCTION__, (set ? "set" : "get"), address, size, dsize));
            bcmerror = BCME_BADARG;
            break;
        }
        DBUSTRACE(("%s: Request to %s %d bytes at address 0x%08x\n", __FUNCTION__,
                   (set ? "write" : "read"), size, address));

        /* Generate the actual data pointer */
        data = set ? (uint8*)params + 2 * sizeof(int): (uint8*)arg;

        /* Call to do the transfer */
        bcmerror = dbus_usb_dl_writeimage(BUS_INFO(bus, usb_info_t), data, size);
    }
    break;


    case IOV_SVAL(IOV_SET_DOWNLOAD_STATE):

        if (bool_val == TRUE) {
            bcmerror = dbus_usb_dlneeded(bus);
            dbus_usb_rdl_dwnld_state(BUS_INFO(bus, usb_info_t));
        } else {
            usb_info_t *usbinfo = BUS_INFO(bus, usb_info_t);
            bcmerror = dbus_usb_dlrun(bus);
            usbinfo->pub->busstate = DBUS_STATE_DL_DONE;
        }
        break;

    case IOV_GVAL(IOV_HSIC_SLEEP):
        bool_val = dbus_usb_sleep_resume_state(BUS_INFO(bus, usb_info_t));
        bcopy(&bool_val, arg, val_size);
        break;

    case IOV_SVAL(IOV_HSIC_SLEEP):
        bcmerror = dbus_usb_sleep(BUS_INFO(bus, usb_info_t), bool_val);
        break;

    case IOV_GVAL(IOV_HSIC_AUTOSLEEP):
        bool_val = dbus_usb_autosleep_state(BUS_INFO(bus, usb_info_t));
        bcopy(&bool_val, arg, val_size);
        break;

    case IOV_SVAL(IOV_HSIC_AUTOSLEEP):
        bcmerror = dbus_usb_autosleep(BUS_INFO(bus, usb_info_t), bool_val);
        break;

    case IOV_SVAL(IOV_VARS):
        bcmerror = dhdusb_downloadvars(BUS_INFO(bus, usb_info_t), arg, len);
        break;

    default:
        bcmerror = BCME_UNSUPPORTED;
        break;
    }

exit:
    return bcmerror;
}