cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

bt3c_cs.c (15085B)


      1/*
      2 *
      3 *  Driver for the 3Com Bluetooth PCMCIA card
      4 *
      5 *  Copyright (C) 2001-2002  Marcel Holtmann <marcel@holtmann.org>
      6 *                           Jose Orlando Pereira <jop@di.uminho.pt>
      7 *
      8 *
      9 *  This program is free software; you can redistribute it and/or modify
     10 *  it under the terms of the GNU General Public License version 2 as
     11 *  published by the Free Software Foundation;
     12 *
     13 *  Software distributed under the License is distributed on an "AS
     14 *  IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
     15 *  implied. See the License for the specific language governing
     16 *  rights and limitations under the License.
     17 *
     18 *  The initial developer of the original code is David A. Hinds
     19 *  <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
     20 *  are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
     21 *
     22 */
     23
     24#include <linux/module.h>
     25
     26#include <linux/kernel.h>
     27#include <linux/init.h>
     28#include <linux/slab.h>
     29#include <linux/types.h>
     30#include <linux/delay.h>
     31#include <linux/errno.h>
     32#include <linux/ptrace.h>
     33#include <linux/ioport.h>
     34#include <linux/spinlock.h>
     35#include <linux/moduleparam.h>
     36
     37#include <linux/skbuff.h>
     38#include <linux/string.h>
     39#include <linux/serial.h>
     40#include <linux/serial_reg.h>
     41#include <linux/bitops.h>
     42#include <asm/io.h>
     43
     44#include <linux/device.h>
     45#include <linux/firmware.h>
     46
     47#include <pcmcia/cistpl.h>
     48#include <pcmcia/ciscode.h>
     49#include <pcmcia/ds.h>
     50#include <pcmcia/cisreg.h>
     51
     52#include <net/bluetooth/bluetooth.h>
     53#include <net/bluetooth/hci_core.h>
     54
     55
     56
     57/* ======================== Module parameters ======================== */
     58
     59
     60MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
     61MODULE_DESCRIPTION("Bluetooth driver for the 3Com Bluetooth PCMCIA card");
     62MODULE_LICENSE("GPL");
     63MODULE_FIRMWARE("BT3CPCC.bin");
     64
     65
     66
     67/* ======================== Local structures ======================== */
     68
     69
     70struct bt3c_info {
     71	struct pcmcia_device *p_dev;
     72
     73	struct hci_dev *hdev;
     74
     75	spinlock_t lock;		/* For serializing operations */
     76
     77	struct sk_buff_head txq;
     78	unsigned long tx_state;
     79
     80	unsigned long rx_state;
     81	unsigned long rx_count;
     82	struct sk_buff *rx_skb;
     83};
     84
     85
     86static int bt3c_config(struct pcmcia_device *link);
     87static void bt3c_release(struct pcmcia_device *link);
     88
     89static void bt3c_detach(struct pcmcia_device *p_dev);
     90
     91
     92/* Transmit states  */
     93#define XMIT_SENDING  1
     94#define XMIT_WAKEUP   2
     95#define XMIT_WAITING  8
     96
     97/* Receiver states */
     98#define RECV_WAIT_PACKET_TYPE   0
     99#define RECV_WAIT_EVENT_HEADER  1
    100#define RECV_WAIT_ACL_HEADER    2
    101#define RECV_WAIT_SCO_HEADER    3
    102#define RECV_WAIT_DATA          4
    103
    104
    105
    106/* ======================== Special I/O functions ======================== */
    107
    108
    109#define DATA_L   0
    110#define DATA_H   1
    111#define ADDR_L   2
    112#define ADDR_H   3
    113#define CONTROL  4
    114
    115
    116static inline void bt3c_address(unsigned int iobase, unsigned short addr)
    117{
    118	outb(addr & 0xff, iobase + ADDR_L);
    119	outb((addr >> 8) & 0xff, iobase + ADDR_H);
    120}
    121
    122
    123static inline void bt3c_put(unsigned int iobase, unsigned short value)
    124{
    125	outb(value & 0xff, iobase + DATA_L);
    126	outb((value >> 8) & 0xff, iobase + DATA_H);
    127}
    128
    129
    130static inline void bt3c_io_write(unsigned int iobase, unsigned short addr, unsigned short value)
    131{
    132	bt3c_address(iobase, addr);
    133	bt3c_put(iobase, value);
    134}
    135
    136
    137static inline unsigned short bt3c_get(unsigned int iobase)
    138{
    139	unsigned short value = inb(iobase + DATA_L);
    140
    141	value |= inb(iobase + DATA_H) << 8;
    142
    143	return value;
    144}
    145
    146
    147static inline unsigned short bt3c_read(unsigned int iobase, unsigned short addr)
    148{
    149	bt3c_address(iobase, addr);
    150
    151	return bt3c_get(iobase);
    152}
    153
    154
    155
    156/* ======================== Interrupt handling ======================== */
    157
    158
    159static int bt3c_write(unsigned int iobase, int fifo_size, __u8 *buf, int len)
    160{
    161	int actual = 0;
    162
    163	bt3c_address(iobase, 0x7080);
    164
    165	/* Fill FIFO with current frame */
    166	while (actual < len) {
    167		/* Transmit next byte */
    168		bt3c_put(iobase, buf[actual]);
    169		actual++;
    170	}
    171
    172	bt3c_io_write(iobase, 0x7005, actual);
    173
    174	return actual;
    175}
    176
    177
    178static void bt3c_write_wakeup(struct bt3c_info *info)
    179{
    180	if (!info) {
    181		BT_ERR("Unknown device");
    182		return;
    183	}
    184
    185	if (test_and_set_bit(XMIT_SENDING, &(info->tx_state)))
    186		return;
    187
    188	do {
    189		unsigned int iobase = info->p_dev->resource[0]->start;
    190		register struct sk_buff *skb;
    191		int len;
    192
    193		if (!pcmcia_dev_present(info->p_dev))
    194			break;
    195
    196		skb = skb_dequeue(&(info->txq));
    197		if (!skb) {
    198			clear_bit(XMIT_SENDING, &(info->tx_state));
    199			break;
    200		}
    201
    202		/* Send frame */
    203		len = bt3c_write(iobase, 256, skb->data, skb->len);
    204
    205		if (len != skb->len)
    206			BT_ERR("Very strange");
    207
    208		kfree_skb(skb);
    209
    210		info->hdev->stat.byte_tx += len;
    211
    212	} while (0);
    213}
    214
    215
    216static void bt3c_receive(struct bt3c_info *info)
    217{
    218	unsigned int iobase;
    219	int size = 0, avail;
    220
    221	if (!info) {
    222		BT_ERR("Unknown device");
    223		return;
    224	}
    225
    226	iobase = info->p_dev->resource[0]->start;
    227
    228	avail = bt3c_read(iobase, 0x7006);
    229
    230	bt3c_address(iobase, 0x7480);
    231	while (size < avail) {
    232		size++;
    233		info->hdev->stat.byte_rx++;
    234
    235		/* Allocate packet */
    236		if (!info->rx_skb) {
    237			info->rx_state = RECV_WAIT_PACKET_TYPE;
    238			info->rx_count = 0;
    239			info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
    240			if (!info->rx_skb) {
    241				BT_ERR("Can't allocate mem for new packet");
    242				return;
    243			}
    244		}
    245
    246
    247		if (info->rx_state == RECV_WAIT_PACKET_TYPE) {
    248
    249			hci_skb_pkt_type(info->rx_skb) = inb(iobase + DATA_L);
    250			inb(iobase + DATA_H);
    251
    252			switch (hci_skb_pkt_type(info->rx_skb)) {
    253
    254			case HCI_EVENT_PKT:
    255				info->rx_state = RECV_WAIT_EVENT_HEADER;
    256				info->rx_count = HCI_EVENT_HDR_SIZE;
    257				break;
    258
    259			case HCI_ACLDATA_PKT:
    260				info->rx_state = RECV_WAIT_ACL_HEADER;
    261				info->rx_count = HCI_ACL_HDR_SIZE;
    262				break;
    263
    264			case HCI_SCODATA_PKT:
    265				info->rx_state = RECV_WAIT_SCO_HEADER;
    266				info->rx_count = HCI_SCO_HDR_SIZE;
    267				break;
    268
    269			default:
    270				/* Unknown packet */
    271				BT_ERR("Unknown HCI packet with type 0x%02x received",
    272				       hci_skb_pkt_type(info->rx_skb));
    273				info->hdev->stat.err_rx++;
    274
    275				kfree_skb(info->rx_skb);
    276				info->rx_skb = NULL;
    277				break;
    278
    279			}
    280
    281		} else {
    282
    283			__u8 x = inb(iobase + DATA_L);
    284
    285			skb_put_u8(info->rx_skb, x);
    286			inb(iobase + DATA_H);
    287			info->rx_count--;
    288
    289			if (info->rx_count == 0) {
    290
    291				int dlen;
    292				struct hci_event_hdr *eh;
    293				struct hci_acl_hdr *ah;
    294				struct hci_sco_hdr *sh;
    295
    296				switch (info->rx_state) {
    297
    298				case RECV_WAIT_EVENT_HEADER:
    299					eh = hci_event_hdr(info->rx_skb);
    300					info->rx_state = RECV_WAIT_DATA;
    301					info->rx_count = eh->plen;
    302					break;
    303
    304				case RECV_WAIT_ACL_HEADER:
    305					ah = hci_acl_hdr(info->rx_skb);
    306					dlen = __le16_to_cpu(ah->dlen);
    307					info->rx_state = RECV_WAIT_DATA;
    308					info->rx_count = dlen;
    309					break;
    310
    311				case RECV_WAIT_SCO_HEADER:
    312					sh = hci_sco_hdr(info->rx_skb);
    313					info->rx_state = RECV_WAIT_DATA;
    314					info->rx_count = sh->dlen;
    315					break;
    316
    317				case RECV_WAIT_DATA:
    318					hci_recv_frame(info->hdev, info->rx_skb);
    319					info->rx_skb = NULL;
    320					break;
    321
    322				}
    323
    324			}
    325
    326		}
    327
    328	}
    329
    330	bt3c_io_write(iobase, 0x7006, 0x0000);
    331}
    332
    333
    334static irqreturn_t bt3c_interrupt(int irq, void *dev_inst)
    335{
    336	struct bt3c_info *info = dev_inst;
    337	unsigned int iobase;
    338	int iir;
    339	irqreturn_t r = IRQ_NONE;
    340
    341	if (!info || !info->hdev)
    342		/* our irq handler is shared */
    343		return IRQ_NONE;
    344
    345	iobase = info->p_dev->resource[0]->start;
    346
    347	spin_lock(&(info->lock));
    348
    349	iir = inb(iobase + CONTROL);
    350	if (iir & 0x80) {
    351		int stat = bt3c_read(iobase, 0x7001);
    352
    353		if ((stat & 0xff) == 0x7f) {
    354			BT_ERR("Very strange (stat=0x%04x)", stat);
    355		} else if ((stat & 0xff) != 0xff) {
    356			if (stat & 0x0020) {
    357				int status = bt3c_read(iobase, 0x7002) & 0x10;
    358				bt_dev_info(info->hdev, "Antenna %s",
    359							status ? "out" : "in");
    360			}
    361			if (stat & 0x0001)
    362				bt3c_receive(info);
    363			if (stat & 0x0002) {
    364				clear_bit(XMIT_SENDING, &(info->tx_state));
    365				bt3c_write_wakeup(info);
    366			}
    367
    368			bt3c_io_write(iobase, 0x7001, 0x0000);
    369
    370			outb(iir, iobase + CONTROL);
    371		}
    372		r = IRQ_HANDLED;
    373	}
    374
    375	spin_unlock(&(info->lock));
    376
    377	return r;
    378}
    379
    380
    381
    382/* ======================== HCI interface ======================== */
    383
    384
    385static int bt3c_hci_flush(struct hci_dev *hdev)
    386{
    387	struct bt3c_info *info = hci_get_drvdata(hdev);
    388
    389	/* Drop TX queue */
    390	skb_queue_purge(&(info->txq));
    391
    392	return 0;
    393}
    394
    395
    396static int bt3c_hci_open(struct hci_dev *hdev)
    397{
    398	return 0;
    399}
    400
    401
    402static int bt3c_hci_close(struct hci_dev *hdev)
    403{
    404	bt3c_hci_flush(hdev);
    405
    406	return 0;
    407}
    408
    409
    410static int bt3c_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
    411{
    412	struct bt3c_info *info = hci_get_drvdata(hdev);
    413	unsigned long flags;
    414
    415	switch (hci_skb_pkt_type(skb)) {
    416	case HCI_COMMAND_PKT:
    417		hdev->stat.cmd_tx++;
    418		break;
    419	case HCI_ACLDATA_PKT:
    420		hdev->stat.acl_tx++;
    421		break;
    422	case HCI_SCODATA_PKT:
    423		hdev->stat.sco_tx++;
    424		break;
    425	}
    426
    427	/* Prepend skb with frame type */
    428	memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
    429	skb_queue_tail(&(info->txq), skb);
    430
    431	spin_lock_irqsave(&(info->lock), flags);
    432
    433	bt3c_write_wakeup(info);
    434
    435	spin_unlock_irqrestore(&(info->lock), flags);
    436
    437	return 0;
    438}
    439
    440
    441
    442/* ======================== Card services HCI interaction ======================== */
    443
    444
    445static int bt3c_load_firmware(struct bt3c_info *info,
    446			      const unsigned char *firmware,
    447			      int count)
    448{
    449	char *ptr = (char *) firmware;
    450	char b[9];
    451	unsigned int iobase, tmp, tn;
    452	unsigned long size, addr, fcs;
    453	int i, err = 0;
    454
    455	iobase = info->p_dev->resource[0]->start;
    456
    457	/* Reset */
    458	bt3c_io_write(iobase, 0x8040, 0x0404);
    459	bt3c_io_write(iobase, 0x8040, 0x0400);
    460
    461	udelay(1);
    462
    463	bt3c_io_write(iobase, 0x8040, 0x0404);
    464
    465	udelay(17);
    466
    467	/* Load */
    468	while (count) {
    469		if (ptr[0] != 'S') {
    470			BT_ERR("Bad address in firmware");
    471			err = -EFAULT;
    472			goto error;
    473		}
    474
    475		memset(b, 0, sizeof(b));
    476		memcpy(b, ptr + 2, 2);
    477		if (kstrtoul(b, 16, &size) < 0)
    478			return -EINVAL;
    479
    480		memset(b, 0, sizeof(b));
    481		memcpy(b, ptr + 4, 8);
    482		if (kstrtoul(b, 16, &addr) < 0)
    483			return -EINVAL;
    484
    485		memset(b, 0, sizeof(b));
    486		memcpy(b, ptr + (size * 2) + 2, 2);
    487		if (kstrtoul(b, 16, &fcs) < 0)
    488			return -EINVAL;
    489
    490		memset(b, 0, sizeof(b));
    491		for (tmp = 0, i = 0; i < size; i++) {
    492			memcpy(b, ptr + (i * 2) + 2, 2);
    493			if (kstrtouint(b, 16, &tn))
    494				return -EINVAL;
    495			tmp += tn;
    496		}
    497
    498		if (((tmp + fcs) & 0xff) != 0xff) {
    499			BT_ERR("Checksum error in firmware");
    500			err = -EILSEQ;
    501			goto error;
    502		}
    503
    504		if (ptr[1] == '3') {
    505			bt3c_address(iobase, addr);
    506
    507			memset(b, 0, sizeof(b));
    508			for (i = 0; i < (size - 4) / 2; i++) {
    509				memcpy(b, ptr + (i * 4) + 12, 4);
    510				if (kstrtouint(b, 16, &tmp))
    511					return -EINVAL;
    512				bt3c_put(iobase, tmp);
    513			}
    514		}
    515
    516		ptr   += (size * 2) + 6;
    517		count -= (size * 2) + 6;
    518	}
    519
    520	udelay(17);
    521
    522	/* Boot */
    523	bt3c_address(iobase, 0x3000);
    524	outb(inb(iobase + CONTROL) | 0x40, iobase + CONTROL);
    525
    526error:
    527	udelay(17);
    528
    529	/* Clear */
    530	bt3c_io_write(iobase, 0x7006, 0x0000);
    531	bt3c_io_write(iobase, 0x7005, 0x0000);
    532	bt3c_io_write(iobase, 0x7001, 0x0000);
    533
    534	return err;
    535}
    536
    537
    538static int bt3c_open(struct bt3c_info *info)
    539{
    540	const struct firmware *firmware;
    541	struct hci_dev *hdev;
    542	int err;
    543
    544	spin_lock_init(&(info->lock));
    545
    546	skb_queue_head_init(&(info->txq));
    547
    548	info->rx_state = RECV_WAIT_PACKET_TYPE;
    549	info->rx_count = 0;
    550	info->rx_skb = NULL;
    551
    552	/* Initialize HCI device */
    553	hdev = hci_alloc_dev();
    554	if (!hdev) {
    555		BT_ERR("Can't allocate HCI device");
    556		return -ENOMEM;
    557	}
    558
    559	info->hdev = hdev;
    560
    561	hdev->bus = HCI_PCCARD;
    562	hci_set_drvdata(hdev, info);
    563	SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
    564
    565	hdev->open  = bt3c_hci_open;
    566	hdev->close = bt3c_hci_close;
    567	hdev->flush = bt3c_hci_flush;
    568	hdev->send  = bt3c_hci_send_frame;
    569
    570	/* Load firmware */
    571	err = request_firmware(&firmware, "BT3CPCC.bin", &info->p_dev->dev);
    572	if (err < 0) {
    573		BT_ERR("Firmware request failed");
    574		goto error;
    575	}
    576
    577	err = bt3c_load_firmware(info, firmware->data, firmware->size);
    578
    579	release_firmware(firmware);
    580
    581	if (err < 0) {
    582		BT_ERR("Firmware loading failed");
    583		goto error;
    584	}
    585
    586	/* Timeout before it is safe to send the first HCI packet */
    587	msleep(1000);
    588
    589	/* Register HCI device */
    590	err = hci_register_dev(hdev);
    591	if (err < 0) {
    592		BT_ERR("Can't register HCI device");
    593		goto error;
    594	}
    595
    596	return 0;
    597
    598error:
    599	info->hdev = NULL;
    600	hci_free_dev(hdev);
    601	return err;
    602}
    603
    604
    605static int bt3c_close(struct bt3c_info *info)
    606{
    607	struct hci_dev *hdev = info->hdev;
    608
    609	if (!hdev)
    610		return -ENODEV;
    611
    612	bt3c_hci_close(hdev);
    613
    614	hci_unregister_dev(hdev);
    615	hci_free_dev(hdev);
    616
    617	return 0;
    618}
    619
    620static int bt3c_probe(struct pcmcia_device *link)
    621{
    622	struct bt3c_info *info;
    623
    624	/* Create new info device */
    625	info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
    626	if (!info)
    627		return -ENOMEM;
    628
    629	info->p_dev = link;
    630	link->priv = info;
    631
    632	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
    633		CONF_AUTO_SET_IO;
    634
    635	return bt3c_config(link);
    636}
    637
    638
    639static void bt3c_detach(struct pcmcia_device *link)
    640{
    641	bt3c_release(link);
    642}
    643
    644static int bt3c_check_config(struct pcmcia_device *p_dev, void *priv_data)
    645{
    646	int *try = priv_data;
    647
    648	if (!try)
    649		p_dev->io_lines = 16;
    650
    651	if ((p_dev->resource[0]->end != 8) || (p_dev->resource[0]->start == 0))
    652		return -EINVAL;
    653
    654	p_dev->resource[0]->end = 8;
    655	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
    656	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
    657
    658	return pcmcia_request_io(p_dev);
    659}
    660
    661static int bt3c_check_config_notpicky(struct pcmcia_device *p_dev,
    662				      void *priv_data)
    663{
    664	static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
    665	int j;
    666
    667	if (p_dev->io_lines > 3)
    668		return -ENODEV;
    669
    670	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
    671	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
    672	p_dev->resource[0]->end = 8;
    673
    674	for (j = 0; j < 5; j++) {
    675		p_dev->resource[0]->start = base[j];
    676		p_dev->io_lines = base[j] ? 16 : 3;
    677		if (!pcmcia_request_io(p_dev))
    678			return 0;
    679	}
    680	return -ENODEV;
    681}
    682
    683static int bt3c_config(struct pcmcia_device *link)
    684{
    685	struct bt3c_info *info = link->priv;
    686	int i;
    687	unsigned long try;
    688
    689	/* First pass: look for a config entry that looks normal.
    690	 * Two tries: without IO aliases, then with aliases
    691	 */
    692	for (try = 0; try < 2; try++)
    693		if (!pcmcia_loop_config(link, bt3c_check_config, (void *) try))
    694			goto found_port;
    695
    696	/* Second pass: try to find an entry that isn't picky about
    697	 * its base address, then try to grab any standard serial port
    698	 * address, and finally try to get any free port.
    699	 */
    700	if (!pcmcia_loop_config(link, bt3c_check_config_notpicky, NULL))
    701		goto found_port;
    702
    703	BT_ERR("No usable port range found");
    704	goto failed;
    705
    706found_port:
    707	i = pcmcia_request_irq(link, &bt3c_interrupt);
    708	if (i != 0)
    709		goto failed;
    710
    711	i = pcmcia_enable_device(link);
    712	if (i != 0)
    713		goto failed;
    714
    715	if (bt3c_open(info) != 0)
    716		goto failed;
    717
    718	return 0;
    719
    720failed:
    721	bt3c_release(link);
    722	return -ENODEV;
    723}
    724
    725
    726static void bt3c_release(struct pcmcia_device *link)
    727{
    728	struct bt3c_info *info = link->priv;
    729
    730	bt3c_close(info);
    731
    732	pcmcia_disable_device(link);
    733}
    734
    735
    736static const struct pcmcia_device_id bt3c_ids[] = {
    737	PCMCIA_DEVICE_PROD_ID13("3COM", "Bluetooth PC Card", 0xefce0a31, 0xd4ce9b02),
    738	PCMCIA_DEVICE_NULL
    739};
    740MODULE_DEVICE_TABLE(pcmcia, bt3c_ids);
    741
    742static struct pcmcia_driver bt3c_driver = {
    743	.owner		= THIS_MODULE,
    744	.name		= "bt3c_cs",
    745	.probe		= bt3c_probe,
    746	.remove		= bt3c_detach,
    747	.id_table	= bt3c_ids,
    748};
    749module_pcmcia_driver(bt3c_driver);