Example #1
0
/*
 * download firmware or command by control pipe
 */
static int
wusb_df_send_data(wusb_df_state_t *wusbp,
		unsigned int address,
		const unsigned char *buffer,
		unsigned int size)
{
	int			error = DDI_FAILURE;
	usb_ctrl_setup_t	setup;
	usb_cb_flags_t		cb_flags;
	usb_cr_t		cr;
	mblk_t			*data = NULL;	/* data for USBA */
	uint16_t		data_len;	/* # of bytes want to write */
	uint_t			cnt;		/* # of xfered bytes */

	setup.bmRequestType	= USB_DEV_REQ_TYPE_VENDOR |
	    USB_DEV_REQ_HOST_TO_DEV | USB_DEV_REQ_RCPT_DEV;
	setup.bRequest		= 0xf0;
	setup.attrs		= 0;

	for (cnt = 0; cnt < size; cnt += data_len) {
		data_len = min(size - cnt, 512);

		/* reuse previous mblk if possible */
		if ((data = reallocb(data, data_len, 0)) == NULL) {

			return (USB_FAILURE);
		}
		bcopy(buffer + cnt, data->b_rptr, data_len);
		data->b_wptr += data_len;

		setup.wValue		= (address + cnt) & 0xffff;
		setup.wIndex		= ((address + cnt) >> 16) & 0xffff;
		setup.wLength		= data_len;
		error = usb_pipe_ctrl_xfer_wait(
		    wusbp->wusb_df_reg->dev_default_ph, &setup, &data,
		    &cr, &cb_flags, 0);
		if (error != USB_SUCCESS) {
			USB_DPRINTF_L2(PRINT_MASK_ATTA, wusbp->wusb_df_log_hdl,
			    "wusb_df_send_data: "
			    "send failed rval=%d, cr=%d, cb=0x%x\n",
			    error, cr, cb_flags);

			break;
		}
	}

	if (data) {
		freemsg(data);
	}

	return (error);
}
Example #2
0
/*
 * Allocate a TPI ACK reusing the old message if possible.
 */
mblk_t	*
tpi_ack_alloc(mblk_t *mp, size_t size, uchar_t db_type, t_scalar_t prim)
{
    mblk_t	*omp	= mp;

    if ((mp = reallocb(mp, size, 0)) == NULL) {
        freemsg(omp);
        return (NULL);
    }
    if (mp->b_cont != NULL) {
        freemsg(mp->b_cont);
        mp->b_cont = NULL;
    }
    mp->b_datap->db_type = db_type;
    mp->b_wptr = mp->b_rptr + size;
    ((union T_primitives *)mp->b_rptr)->type = prim;
    return (mp);
}
Example #3
0
/*
 * DL_CAPABILITY_ACK/DL_ERROR_ACK
 */
static void
proto_capability_advertise(dld_str_t *dsp, mblk_t *mp)
{
	dl_capability_ack_t	*dlap;
	dl_capability_sub_t	*dlsp;
	size_t			subsize;
	dl_capab_dld_t		dld;
	dl_capab_hcksum_t	hcksum;
	dl_capab_zerocopy_t	zcopy;
	dl_capab_vrrp_t		vrrp;
	mac_capab_vrrp_t	vrrp_capab;
	uint8_t			*ptr;
	queue_t			*q = dsp->ds_wq;
	mblk_t			*mp1;
	boolean_t		hcksum_capable = B_FALSE;
	boolean_t		zcopy_capable = B_FALSE;
	boolean_t		dld_capable = B_FALSE;
	boolean_t		vrrp_capable = B_FALSE;

	/*
	 * Initially assume no capabilities.
	 */
	subsize = 0;

	/*
	 * Check if checksum offload is supported on this MAC.
	 */
	bzero(&hcksum, sizeof (dl_capab_hcksum_t));
	if (mac_capab_get(dsp->ds_mh, MAC_CAPAB_HCKSUM,
	    &hcksum.hcksum_txflags)) {
		if (hcksum.hcksum_txflags != 0) {
			hcksum_capable = B_TRUE;
			subsize += sizeof (dl_capability_sub_t) +
			    sizeof (dl_capab_hcksum_t);
		}
	}

	/*
	 * Check if zerocopy is supported on this interface.
	 * If advertising DL_CAPAB_ZEROCOPY has not been explicitly disabled
	 * then reserve space for that capability.
	 */
	if (!mac_capab_get(dsp->ds_mh, MAC_CAPAB_NO_ZCOPY, NULL) &&
	    !(dld_opt & DLD_OPT_NO_ZEROCOPY)) {
		zcopy_capable = B_TRUE;
		subsize += sizeof (dl_capability_sub_t) +
		    sizeof (dl_capab_zerocopy_t);
	}

	/*
	 * Direct capability negotiation interface between IP and DLD
	 */
	if (dsp->ds_sap == ETHERTYPE_IP && check_mod_above(dsp->ds_rq, "ip")) {
		dld_capable = B_TRUE;
		subsize += sizeof (dl_capability_sub_t) +
		    sizeof (dl_capab_dld_t);
	}

	/*
	 * Check if vrrp is supported on this interface. If so, reserve
	 * space for that capability.
	 */
	if (mac_capab_get(dsp->ds_mh, MAC_CAPAB_VRRP, &vrrp_capab)) {
		vrrp_capable = B_TRUE;
		subsize += sizeof (dl_capability_sub_t) +
		    sizeof (dl_capab_vrrp_t);
	}

	/*
	 * If there are no capabilities to advertise or if we
	 * can't allocate a response, send a DL_ERROR_ACK.
	 */
	if ((mp1 = reallocb(mp,
	    sizeof (dl_capability_ack_t) + subsize, 0)) == NULL) {
		dlerrorack(q, mp, DL_CAPABILITY_REQ, DL_NOTSUPPORTED, 0);
		return;
	}

	mp = mp1;
	DB_TYPE(mp) = M_PROTO;
	mp->b_wptr = mp->b_rptr + sizeof (dl_capability_ack_t) + subsize;
	bzero(mp->b_rptr, MBLKL(mp));
	dlap = (dl_capability_ack_t *)mp->b_rptr;
	dlap->dl_primitive = DL_CAPABILITY_ACK;
	dlap->dl_sub_offset = sizeof (dl_capability_ack_t);
	dlap->dl_sub_length = subsize;
	ptr = (uint8_t *)&dlap[1];

	/*
	 * TCP/IP checksum offload.
	 */
	if (hcksum_capable) {
		dlsp = (dl_capability_sub_t *)ptr;

		dlsp->dl_cap = DL_CAPAB_HCKSUM;
		dlsp->dl_length = sizeof (dl_capab_hcksum_t);
		ptr += sizeof (dl_capability_sub_t);

		hcksum.hcksum_version = HCKSUM_VERSION_1;
		dlcapabsetqid(&(hcksum.hcksum_mid), dsp->ds_rq);
		bcopy(&hcksum, ptr, sizeof (dl_capab_hcksum_t));
		ptr += sizeof (dl_capab_hcksum_t);
	}

	/*
	 * Zero copy
	 */
	if (zcopy_capable) {
		dlsp = (dl_capability_sub_t *)ptr;

		dlsp->dl_cap = DL_CAPAB_ZEROCOPY;
		dlsp->dl_length = sizeof (dl_capab_zerocopy_t);
		ptr += sizeof (dl_capability_sub_t);

		bzero(&zcopy, sizeof (dl_capab_zerocopy_t));
		zcopy.zerocopy_version = ZEROCOPY_VERSION_1;
		zcopy.zerocopy_flags = DL_CAPAB_VMSAFE_MEM;

		dlcapabsetqid(&(zcopy.zerocopy_mid), dsp->ds_rq);
		bcopy(&zcopy, ptr, sizeof (dl_capab_zerocopy_t));
		ptr += sizeof (dl_capab_zerocopy_t);
	}

	/*
	 * VRRP capability negotiation
	 */
	if (vrrp_capable) {
		dlsp = (dl_capability_sub_t *)ptr;
		dlsp->dl_cap = DL_CAPAB_VRRP;
		dlsp->dl_length = sizeof (dl_capab_vrrp_t);
		ptr += sizeof (dl_capability_sub_t);

		bzero(&vrrp, sizeof (dl_capab_vrrp_t));
		vrrp.vrrp_af = vrrp_capab.mcv_af;
		bcopy(&vrrp, ptr, sizeof (dl_capab_vrrp_t));
		ptr += sizeof (dl_capab_vrrp_t);
	}

	/*
	 * Direct capability negotiation interface between IP and DLD.
	 * Refer to dld.h for details.
	 */
	if (dld_capable) {
		dlsp = (dl_capability_sub_t *)ptr;
		dlsp->dl_cap = DL_CAPAB_DLD;
		dlsp->dl_length = sizeof (dl_capab_dld_t);
		ptr += sizeof (dl_capability_sub_t);

		bzero(&dld, sizeof (dl_capab_dld_t));
		dld.dld_version = DLD_CURRENT_VERSION;
		dld.dld_capab = (uintptr_t)dld_capab;
		dld.dld_capab_handle = (uintptr_t)dsp;

		dlcapabsetqid(&(dld.dld_mid), dsp->ds_rq);
		bcopy(&dld, ptr, sizeof (dl_capab_dld_t));
		ptr += sizeof (dl_capab_dld_t);
	}

	ASSERT(ptr == mp->b_rptr + sizeof (dl_capability_ack_t) + subsize);
	qreply(q, mp);
}