Exemplo n.º 1
0
static int bt3c_write(unsigned int iobase, int fifo_size, __u8 *buf, int len)
{
	int actual = 0;

	bt3c_address(iobase, 0x7080);

	/* Fill FIFO with current frame */
	while (actual < len) {
		/* Transmit next byte */
		bt3c_put(iobase, buf[actual]);
		actual++;
	}

	bt3c_io_write(iobase, 0x7005, actual);

	return actual;
}
Exemplo n.º 2
0
static void bt3c_receive(bt3c_info_t *info)
{
	unsigned int iobase;
	int size = 0, avail;

	if (!info) {
		printk(KERN_WARNING "bt3c_cs: Call of receive for unknown device.\n");
		return;
	}

	iobase = info->link.io.BasePort1;

	avail = bt3c_read(iobase, 0x7006);
	//printk("bt3c_cs: receiving %d bytes\n", avail);

	bt3c_address(iobase, 0x7480);
	while (size < avail) {
		size++;
		info->hdev.stat.byte_rx++;

		/* Allocate packet */
		if (info->rx_skb == NULL) {
			info->rx_state = RECV_WAIT_PACKET_TYPE;
			info->rx_count = 0;
			if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
				printk(KERN_WARNING "bt3c_cs: Can't allocate mem for new packet.\n");
				return;
			}
		}


		if (info->rx_state == RECV_WAIT_PACKET_TYPE) {

			info->rx_skb->dev = (void *)&(info->hdev);
			info->rx_skb->pkt_type = inb(iobase + DATA_L);
			inb(iobase + DATA_H);
			//printk("bt3c: PACKET_TYPE=%02x\n", info->rx_skb->pkt_type);

			switch (info->rx_skb->pkt_type) {

			case HCI_EVENT_PKT:
				info->rx_state = RECV_WAIT_EVENT_HEADER;
				info->rx_count = HCI_EVENT_HDR_SIZE;
				break;

			case HCI_ACLDATA_PKT:
				info->rx_state = RECV_WAIT_ACL_HEADER;
				info->rx_count = HCI_ACL_HDR_SIZE;
				break;

			case HCI_SCODATA_PKT:
				info->rx_state = RECV_WAIT_SCO_HEADER;
				info->rx_count = HCI_SCO_HDR_SIZE;
				break;

			default:
				/* Unknown packet */
				printk(KERN_WARNING "bt3c_cs: Unknown HCI packet with type 0x%02x received.\n", info->rx_skb->pkt_type);
				info->hdev.stat.err_rx++;
				clear_bit(HCI_RUNNING, &(info->hdev.flags));

				dev_kfree_skb_any(info->rx_skb);
				info->rx_skb = NULL;
				break;

			}

		} else {

			__u8 x = inb(iobase + DATA_L);

			*skb_put(info->rx_skb, 1) = x;
			inb(iobase + DATA_H);
			info->rx_count--;

			if (info->rx_count == 0) {

				int dlen;
				struct hci_event_hdr *eh;
				struct hci_acl_hdr *ah;
				struct hci_sco_hdr *sh;

				switch (info->rx_state) {

				case RECV_WAIT_EVENT_HEADER:
					eh = (struct hci_event_hdr *)(info->rx_skb->data);
					info->rx_state = RECV_WAIT_DATA;
					info->rx_count = eh->plen;
					break;

				case RECV_WAIT_ACL_HEADER:
					ah = (struct hci_acl_hdr *)(info->rx_skb->data);
					dlen = __le16_to_cpu(ah->dlen);
					info->rx_state = RECV_WAIT_DATA;
					info->rx_count = dlen;
					break;

				case RECV_WAIT_SCO_HEADER:
					sh = (struct hci_sco_hdr *)(info->rx_skb->data);
					info->rx_state = RECV_WAIT_DATA;
					info->rx_count = sh->dlen;
					break;

				case RECV_WAIT_DATA:
					hci_recv_frame(info->rx_skb);
					info->rx_skb = NULL;
					break;

				}

			}

		}

	}

	bt3c_io_write(iobase, 0x7006, 0x0000);
}
Exemplo n.º 3
0
inline void bt3c_io_write(unsigned int iobase, unsigned short addr, unsigned short value)
{
	bt3c_address(iobase, addr);
	bt3c_put(iobase, value);
}
Exemplo n.º 4
0
inline unsigned short bt3c_read(unsigned int iobase, unsigned short addr)
{
	bt3c_address(iobase, addr);

	return bt3c_get(iobase);
}
Exemplo n.º 5
0
static int bt3c_load_firmware(bt3c_info_t *info, unsigned char *firmware, int count)
{
	char *ptr = (char *) firmware;
	char b[9];
	unsigned int iobase, size, addr, fcs, tmp;
	int i, err = 0;

	iobase = info->link.io.BasePort1;

	/* Reset */
	bt3c_io_write(iobase, 0x8040, 0x0404);
	bt3c_io_write(iobase, 0x8040, 0x0400);

	udelay(1);

	bt3c_io_write(iobase, 0x8040, 0x0404);

	udelay(17);

	/* Load */
	while (count) {
		if (ptr[0] != 'S') {
			BT_ERR("Bad address in firmware");
			err = -EFAULT;
			goto error;
		}

		memset(b, 0, sizeof(b));
		memcpy(b, ptr + 2, 2);
		size = simple_strtol(b, NULL, 16);

		memset(b, 0, sizeof(b));
		memcpy(b, ptr + 4, 8);
		addr = simple_strtol(b, NULL, 16);

		memset(b, 0, sizeof(b));
		memcpy(b, ptr + (size * 2) + 2, 2);
		fcs = simple_strtol(b, NULL, 16);

		memset(b, 0, sizeof(b));
		for (tmp = 0, i = 0; i < size; i++) {
			memcpy(b, ptr + (i * 2) + 2, 2);
			tmp += simple_strtol(b, NULL, 16);
		}

		if (((tmp + fcs) & 0xff) != 0xff) {
			BT_ERR("Checksum error in firmware");
			err = -EILSEQ;
			goto error;
		}

		if (ptr[1] == '3') {
			bt3c_address(iobase, addr);

			memset(b, 0, sizeof(b));
			for (i = 0; i < (size - 4) / 2; i++) {
				memcpy(b, ptr + (i * 4) + 12, 4);
				tmp = simple_strtol(b, NULL, 16);
				bt3c_put(iobase, tmp);
			}
		}

		ptr   += (size * 2) + 6;
		count -= (size * 2) + 6;
	}

	udelay(17);

	/* Boot */
	bt3c_address(iobase, 0x3000);
	outb(inb(iobase + CONTROL) | 0x40, iobase + CONTROL);

error:
	udelay(17);

	/* Clear */
	bt3c_io_write(iobase, 0x7006, 0x0000);
	bt3c_io_write(iobase, 0x7005, 0x0000);
	bt3c_io_write(iobase, 0x7001, 0x0000);

	return err;
}