/* * QEMU Bluetooth HCI USB Transport Layer v1.0 * * Copyright (C) 2007 OpenMoko, Inc. * Copyright (C) 2008 Andrzej Zaborowski * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see . */ #include "qemu-common.h" #include "qemu/error-report.h" #include "hw/usb.h" #include "hw/usb/desc.h" #include "sysemu/bt.h" #include "hw/bt.h" struct USBBtState { USBDevice dev; struct HCIInfo *hci; USBEndpoint *intr; int config; #define CFIFO_LEN_MASK 255 #define DFIFO_LEN_MASK 4095 struct usb_hci_in_fifo_s { uint8_t data[(DFIFO_LEN_MASK + 1) * 2]; struct { uint8_t *data; int len; } fifo[CFIFO_LEN_MASK + 1]; int dstart, dlen, dsize, start, len; } evt, acl, sco; struct usb_hci_out_fifo_s { uint8_t data[4096]; int len; } outcmd, outacl, outsco; }; #define TYPE_USB_BT "usb-bt-dongle" #define USB_BT(obj) OBJECT_CHECK(struct USBBtState, (obj), TYPE_USB_BT) #define USB_EVT_EP 1 #define USB_ACL_EP 2 #define USB_SCO_EP 3 enum { STR_MANUFACTURER = 1, STR_SERIALNUMBER, }; static const USBDescStrings desc_strings = { [STR_MANUFACTURER] = "QEMU", [STR_SERIALNUMBER] = "1", }; static const USBDescIface desc_iface_bluetooth[] = { { .bInterfaceNumber = 0, .bNumEndpoints = 3, .bInterfaceClass = 0xe0, /* Wireless */ .bInterfaceSubClass = 0x01, /* Radio Frequency */ .bInterfaceProtocol = 0x01, /* Bluetooth */ .eps = (USBDescEndpoint[]) { { .bEndpointAddress = USB_DIR_IN | USB_EVT_EP, .bmAttributes = USB_ENDPOINT_XFER_INT, .wMaxPacketSize = 0x10, .bInterval = 0x02, }, { .bEndpointAddress = USB_DIR_OUT | USB_ACL_EP, .bmAttributes = USB_ENDPOINT_XFER_BULK, .wMaxPacketSize = 0x40, .bInterval = 0x0a, }, { .bEndpointAddress = USB_DIR_IN | USB_ACL_EP, .bmAttributes = USB_ENDPOINT_XFER_BULK, .wMaxPacketSize = 0x40, .bInterval = 0x0a, }, }, },{ .bInterfaceNumber = 1, .bAlternateSetting = 0, .bNumEndpoints = 2, .bInterfaceClass = 0xe0, /* Wireless */ .bInterfaceSubClass = 0x01, /* Radio Frequency */ .bInterfaceProtocol = 0x01, /* Bluetooth */ .eps = (USBDescEndpoint[]) { { .bEndpointAddress = USB_DIR_OUT | USB_SCO_EP, .bmAttributes = USB_ENDPOINT_XFER_ISOC, .wMaxPacketSize = 0, .bInterval = 0x01, }, { .bEndpointAddress = USB_DIR_IN | USB_SCO_EP, .bmAttributes = USB_ENDPOINT_XFER_ISOC, .wMaxPacketSize = 0, .bInterval = 0x01, }, }, },{ .bInterfaceNumber = 1, .bAlternateSetting = 1, .bNumEndpoints = 2, .bInterfaceClass = 0xe0, /* Wireless */ .bInterfaceSubClass = 0x01, /* Radio Frequency */ .bInterfaceProtocol = 0x01, /* Bluetooth */ .eps = (USBDescEndpoint[]) { { .bEndpointAddress = USB_DIR_OUT | USB_SCO_EP, .bmAttributes = USB_ENDPOINT_XFER_ISOC, .wMaxPacketSize = 0x09, .bInterval = 0x01, }, { .bEndpointAddress = USB_DIR_IN | USB_SCO_EP, .bmAttributes = USB_ENDPOINT_XFER_ISOC, .wMaxPacketSize = 0x09, .bInterval = 0x01, }, }, },{ .bInterfaceNumber = 1, .bAlternateSetting = 2, .bNumEndpoints = 2, .bInterfaceClass = 0xe0, /* Wireless */ .bInterfaceSubClass = 0x01, /* Radio Frequency */ .bInterfaceProtocol = 0x01, /* Bluetooth */ .eps = (USBDescEndpoint[]) { { .bEndpointAddress = USB_DIR_OUT | USB_SCO_EP, .bmAttributes = USB_ENDPOINT_XFER_ISOC, .wMaxPacketSize = 0x11, .bInterval = 0x01, }, { .bEndpointAddress = USB_DIR_IN | USB_SCO_EP, .bmAttributes = USB_ENDPOINT_XFER_ISOC, .wMaxPacketSize = 0x11, .bInterval = 0x01, }, }, },{ .bInterfaceNumber = 1, .bAlternateSetting = 3, .bNumEndpoints = 2, .bInterfaceClass = 0xe0, /* Wireless */ .bInterfaceSubClass = 0x01, /* Radio Frequency */ .bInterfaceProtocol = 0x01, /* Bluetooth */ .eps = (USBDescEndpoint[]) { { .bEndpointAddress = USB_DIR_OUT | USB_SCO_EP, .bmAttributes = USB_ENDPOINT_XFER_ISOC, .wMaxPacketSize = 0x19, .bInterval = 0x01, }, { .bEndpointAddress = USB_DIR_IN | USB_SCO_EP, .bmAttributes = USB_ENDPOINT_XFER_ISOC, .wMaxPacketSize = 0x19, .bInterval = 0x01, }, }, },{ .bInterfaceNumber = 1, .bAlternateSetting = 4, .bNumEndpoints = 2, .bInterfaceClass = 0xe0, /* Wireless */ .bInterfaceSubClass = 0x01, /* Radio Frequency */ .bInterfaceProtocol = 0x01, /* Bluetooth */ .eps = (USBDescEndpoint[]) { { .bEndpointAddress = USB_DIR_OUT | USB_SCO_EP, .bmAttributes = USB_ENDPOINT_XFER_ISOC, .wMaxPacketSize = 0x21, .bInterval = 0x01, }, { .bEndpointAddress = USB_DIR_IN | USB_SCO_EP, .bmAttributes = USB_ENDPOINT_XFER_ISOC, .wMaxPacketSize = 0x21, .bInterval = 0x01, }, }, },{ .bInterfaceNumber = 1, .bAlternateSetting = 5, .bNumEndpoints = 2, .bInterfaceClass = 0xe0, /* Wireless */ .bInterfaceSubClass = 0x01, /* Radio
/*
 * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/linkage.h>

#undef PREALLOC_NOT_AVAIL

ENTRY(memset)
	prefetchw [r0]		; Prefetch the write location
	mov.f	0, r2
;;; if size is zero
	jz.d	[blink]
	mov	r3, r0		; don't clobber ret val

;;; if length < 8
	brls.d.nt	r2, 8, .Lsmallchunk
	mov.f	lp_count,r2

	and.f	r4, r0, 0x03
	rsub	lp_count, r4, 4
	lpnz	@.Laligndestination
	;; LOOP BEGIN
	stb.ab	r1, [r3,1]
	sub	r2, r2, 1
.Laligndestination:

;;; Destination is aligned
	and	r1, r1, 0xFF
	asl	r4, r1, 8
	or	r4, r4, r1
	asl	r5, r4, 16
	or	r5, r5, r4
	mov	r4, r5

	sub3	lp_count, r2, 8
	cmp     r2, 64
	bmsk.hi	r2, r2, 5
	mov.ls	lp_count, 0
	add3.hi	r2, r2, 8

;;; Convert len to Dwords, unfold x8
	lsr.f	lp_count, lp_count, 6

	lpnz	@.Lset64bytes
	;; LOOP START
#ifdef PREALLOC_NOT_AVAIL
	prefetchw [r3, 64]	;Prefetch the next write location
#else
	prealloc  [r3, 64]
#endif
#ifdef CONFIG_ARC_HAS_LL64
	std.ab	r4, [r3, 8]
	std.ab	r4, [r3, 8]
	std.ab	r4, [r3, 8]
	std.ab	r4, [r3, 8]
	std.ab	r4, [r3, 8]
	std.ab	r4, [r3, 8]
	std.ab	r4, [r3, 8]
	std.ab	r4, [r3, 8]
#else
	st.ab	r4, [r3, 4]
	st.ab	r4, [r3, 4]
	st.ab	r4, [r3, 4]
	st.ab	r4, [r3, 4]
	st.ab	r4, [r3, 4]