bt3c.c revision 1.1.10.1
1/* $NetBSD: bt3c.c,v 1.1.10.1 2006/09/01 14:48:23 tron Exp $ */
2
3/*-
4 * Copyright (c) 2005 Iain D. Hibbert,
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 *    derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/*
31 * Driver for the 3Com Bluetooth PC Card 3CRWB6096, written with reference to
32 *  FreeBSD and BlueZ drivers for same, with credit for those going to:
33 *
34 *		Maksim Yevmenkin <m_evmenkin@yahoo.com>		(FreeBSD)
35 *		Marcel Holtmann <marcel@holtmann.org>		(BlueZ)
36 *		Jose Orlando Pereira <jop@di.uminho.pt>		(BlueZ)
37 *		David Hinds <dahinds@users.sourceforge.net>	(Original Code)
38 */
39
40/*
41 * The CIS info from my card:
42 *
43 *	pcmcia1: CIS tuple chain:
44 *	CISTPL_DEVICE type=null speed=null
45 *	 01 03 00 00 ff
46 *	CISTPL_VERS_1
47 *	 15 24 05 00 33 43 4f 4d 00 33 43 52 57 42 36 30
48 *	 2d 41 00 42 6c 75 65 74 6f 6f 74 68 20 50 43 20
49 *	 43 61 72 64 00 ff
50 *	CISTPL_MANFID
51 *	 20 04 01 01 40 00
52 *	CISTPL_FUNCID
53 *	 21 02 02 01
54 *	CISTPL_CONFIG
55 *	 1a 06 05 30 20 03 17 00
56 *	CISTPL_CFTABLE_ENTRY
57 *	 1b 09 f0 41 18 a0 40 07 30 ff ff
58 *	unhandled CISTPL 80
59 *	 80 0a 02 01 40 00 2d 00 00 00 00 ff
60 *	CISTPL_NO_LINK
61 *	 14 00
62 *	CISTPL_END
63 *	 ff
64 *	pcmcia1: CIS version PC Card Standard 5.0
65 *	pcmcia1: CIS info: 3COM, 3CRWB60-A, Bluetooth PC Card
66 *	pcmcia1: Manufacturer code 0x101, product 0x40
67 *	pcmcia1: function 0: serial port, ccr addr 320 mask 17
68 *	pcmcia1: function 0, config table entry 48: I/O card; irq mask ffff; iomask 0, iospace 0-7; rdybsy_active io8 irqlevel
69 */
70
71#include <sys/cdefs.h>
72__KERNEL_RCSID(0, "$NetBSD: bt3c.c,v 1.1.10.1 2006/09/01 14:48:23 tron Exp $");
73
74#include <sys/param.h>
75#include <sys/device.h>
76#include <sys/mbuf.h>
77#include <sys/systm.h>
78
79#include <machine/cpu.h>
80#include <machine/bus.h>
81#include <machine/intr.h>
82
83#include <dev/pcmcia/pcmciareg.h>
84#include <dev/pcmcia/pcmciavar.h>
85#include <dev/pcmcia/pcmciadevs.h>
86
87#include <netbt/bluetooth.h>
88#include <netbt/hci.h>
89
90#include <dev/firmload.h>
91#define BT3C_FIRMWARE_FILE	"BT3CPCC.bin"
92
93/**************************************************************************
94 *
95 *	bt3c autoconfig glue
96 */
97
98struct bt3c_softc {
99	struct device	sc_dev;			/* required */
100
101	struct pcmcia_function *sc_pf;		/* our PCMCIA function */
102	struct pcmcia_io_handle sc_pcioh;	/* PCMCIA i/o space info */
103	int		sc_iow;			/* our i/o window */
104	void		*sc_powerhook;		/* power hook descriptor */
105	int		sc_flags;		/* flags */
106
107	struct hci_unit sc_unit;		/* Bluetooth HCI Unit */
108
109	/* hardware interrupt */
110	void		*sc_intr;		/* cookie */
111	int		sc_state;		/* receive state */
112	int		sc_want;		/* how much we want */
113	struct mbuf	*sc_rxp;		/* incoming packet */
114	struct mbuf	*sc_txp;		/* outgoing packet */
115};
116
117/* sc_state */				/* receiving */
118#define BT3C_RECV_PKT_TYPE	0		/* packet type */
119#define BT3C_RECV_ACL_HDR	1		/* acl header */
120#define BT3C_RECV_SCO_HDR	2		/* sco header */
121#define BT3C_RECV_EVENT_HDR	3		/* event header */
122#define BT3C_RECV_ACL_DATA	4		/* acl packet data */
123#define BT3C_RECV_SCO_DATA	5		/* sco packet data */
124#define BT3C_RECV_EVENT_DATA	6		/* event packet data */
125
126/* sc_flags */
127#define BT3C_SLEEPING		(1 << 0)	/* but not with the fishes */
128
129static int bt3c_match(struct device *, struct cfdata *, void *);
130static void bt3c_attach(struct device *, struct device *, void *);
131static int bt3c_detach(struct device *, int);
132static int bt3c_activate(struct device *, enum devact);
133static void bt3c_power(int, void *);
134
135CFATTACH_DECL(bt3c, sizeof(struct bt3c_softc),
136    bt3c_match, bt3c_attach, bt3c_detach, bt3c_activate);
137
138static void bt3c_start(struct hci_unit *);
139static int bt3c_enable(struct hci_unit *);
140static void bt3c_disable(struct hci_unit *);
141
142/**************************************************************************
143 *
144 *	Hardware Definitions & IO routines
145 *
146 *	I made up the names for most of these defs since we dont have
147 *	manufacturers recommendations, but I dont like raw numbers..
148 *
149 *	all hardware routines are running at IPL_TTY
150 *
151 */
152#define BT3C_ISR		0x7001		/* Interrupt Status Register */
153#define BT3C_ISR_RXRDY			(1<<0)	/* Device has data */
154#define BT3C_ISR_TXRDY			(1<<1)	/* Finished sending data */
155#define BT3C_ISR_ANTENNA		(1<<5)	/* Antenna position changed */
156
157#define BT3C_CSR		0x7002		/* Card Status Register */
158#define BT3C_CSR_ANTENNA		(1<<4)	/* Antenna position */
159
160#define BT3C_TX_COUNT		0x7005		/* Tx fifo contents */
161#define BT3C_TX_FIFO		0x7080		/* Transmit Fifo */
162#define BT3C_RX_COUNT		0x7006		/* Rx fifo contents */
163#define BT3C_RX_FIFO		0x7480		/* Receive Fifo */
164#define BT3C_FIFO_SIZE			256
165
166/* IO Registers */
167#define BT3C_IOR_DATA_L		0x00		/* data low byte */
168#define BT3C_IOR_DATA_H		0x01		/* data high byte */
169#define BT3C_IOR_ADDR_L		0x02		/* address low byte */
170#define BT3C_IOR_ADDR_H		0x03		/* address high byte */
171#define BT3C_IOR_CNTL		0x04		/* control byte */
172#define BT3C_IOR_CNTL_BOOT		(1<<6)	/* Boot Card */
173#define BT3C_IOR_CNTL_INTR		(1<<7)	/* Interrupt Requested */
174#define BT3C_IOR_LEN		0x05
175
176static inline uint16_t
177bt3c_get(struct bt3c_softc *sc)
178{
179	uint16_t data;
180
181	bus_space_barrier(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
182				0, BT3C_IOR_LEN, BUS_SPACE_BARRIER_READ);
183	data = bus_space_read_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
184				BT3C_IOR_DATA_L);
185	data |= bus_space_read_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
186				BT3C_IOR_DATA_H) << 8;
187
188	return data;
189}
190
191static inline void
192bt3c_put(struct bt3c_softc *sc, uint16_t data)
193{
194
195	bus_space_barrier(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
196			0, BT3C_IOR_LEN, BUS_SPACE_BARRIER_WRITE);
197	bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
198			BT3C_IOR_DATA_L, data & 0xff);
199	bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
200			BT3C_IOR_DATA_H, (data >> 8) & 0xff);
201}
202
203static inline uint8_t
204bt3c_read_control(struct bt3c_softc *sc)
205{
206
207	bus_space_barrier(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
208			0, BT3C_IOR_LEN, BUS_SPACE_BARRIER_READ);
209	return bus_space_read_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
210			BT3C_IOR_CNTL);
211}
212
213static inline void
214bt3c_write_control(struct bt3c_softc *sc, uint8_t data)
215{
216
217	bus_space_barrier(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
218			0, BT3C_IOR_LEN, BUS_SPACE_BARRIER_WRITE);
219	bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
220			BT3C_IOR_CNTL, data);
221}
222
223static inline void
224bt3c_set_address(struct bt3c_softc *sc, uint16_t addr)
225{
226
227	bus_space_barrier(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
228			0, BT3C_IOR_LEN, BUS_SPACE_BARRIER_WRITE);
229	bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
230			BT3C_IOR_ADDR_L, addr & 0xff);
231	bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
232			BT3C_IOR_ADDR_H, (addr >> 8) & 0xff);
233}
234
235static inline uint16_t
236bt3c_read(struct bt3c_softc *sc, uint16_t addr)
237{
238
239	bt3c_set_address(sc, addr);
240	return bt3c_get(sc);
241}
242
243static inline void
244bt3c_write(struct bt3c_softc *sc, uint16_t addr, uint16_t data)
245{
246
247	bt3c_set_address(sc, addr);
248	bt3c_put(sc, data);
249}
250
251/*
252 * receive incoming data from device, store in mbuf chain and
253 * pass on complete packets to bt device
254 */
255static void
256bt3c_receive(struct bt3c_softc *sc)
257{
258	struct mbuf *m = sc->sc_rxp;
259	int space = 0;
260	uint16_t count;
261	uint8_t b;
262
263	/*
264	 * If we already started a packet, find the
265	 * trailing end of it.
266	 */
267	if (m) {
268		while (m->m_next)
269			m = m->m_next;
270
271		space = M_TRAILINGSPACE(m);
272	}
273
274	count = bt3c_read(sc, BT3C_RX_COUNT);
275	bt3c_set_address(sc, BT3C_RX_FIFO);
276
277	while (count > 0) {
278		if (space == 0) {
279			if (m == NULL) {
280				/* new packet */
281				MGETHDR(m, M_DONTWAIT, MT_DATA);
282				if (m == NULL) {
283					printf("%s: out of memory\n",
284						sc->sc_dev.dv_xname);
285					++sc->sc_unit.hci_stats.err_rx;
286					goto out;	/* (lost sync) */
287				}
288
289				sc->sc_rxp = m;
290				m->m_pkthdr.len = m->m_len = 0;
291				space = MHLEN;
292
293				sc->sc_state = BT3C_RECV_PKT_TYPE;
294				sc->sc_want = 1;
295			} else {
296				/* extend mbuf */
297				MGET(m->m_next, M_DONTWAIT, MT_DATA);
298				if (m->m_next == NULL) {
299					printf("%s: out of memory\n",
300						sc->sc_dev.dv_xname);
301					++sc->sc_unit.hci_stats.err_rx;
302					goto out;	/* (lost sync) */
303				}
304
305				m = m->m_next;
306				m->m_len = 0;
307				space = MLEN;
308
309				if (sc->sc_want > MINCLSIZE) {
310					MCLGET(m, M_DONTWAIT);
311					if (m->m_flags & M_EXT)
312						space = MCLBYTES;
313				}
314			}
315		}
316
317		b = bt3c_get(sc);
318		mtod(m, uint8_t *)[m->m_len++] = b;
319		count--;
320		space--;
321		sc->sc_rxp->m_pkthdr.len++;
322		sc->sc_unit.hci_stats.byte_rx++;
323
324		sc->sc_want--;
325		if (sc->sc_want > 0)
326			continue; /* want more */
327
328		switch (sc->sc_state) {
329		case BT3C_RECV_PKT_TYPE:		/* Got packet type */
330
331			switch (b) {
332			case HCI_ACL_DATA_PKT:
333				sc->sc_state = BT3C_RECV_ACL_HDR;
334				sc->sc_want = sizeof(hci_acldata_hdr_t) - 1;
335				break;
336
337			case HCI_SCO_DATA_PKT:
338				sc->sc_state = BT3C_RECV_SCO_HDR;
339				sc->sc_want = sizeof(hci_scodata_hdr_t) - 1;
340				break;
341
342			case HCI_EVENT_PKT:
343				sc->sc_state = BT3C_RECV_EVENT_HDR;
344				sc->sc_want = sizeof(hci_event_hdr_t) - 1;
345				break;
346
347			default:
348				printf("%s: Unknown packet type=%#x!\n",
349					sc->sc_dev.dv_xname, b);
350				++sc->sc_unit.hci_stats.err_rx;
351				m_freem(sc->sc_rxp);
352				sc->sc_rxp = NULL;
353				goto out;	/* (lost sync) */
354			}
355
356			break;
357
358		/*
359		 * we assume (correctly of course :) that the packet headers
360		 * all fit into a single pkthdr mbuf
361		 */
362		case BT3C_RECV_ACL_HDR:		/* Got ACL Header */
363			sc->sc_state = BT3C_RECV_ACL_DATA;
364			sc->sc_want = mtod(m, hci_acldata_hdr_t *)->length;
365			sc->sc_want = le16toh(sc->sc_want);
366			break;
367
368		case BT3C_RECV_SCO_HDR:		/* Got SCO Header */
369			sc->sc_state = BT3C_RECV_SCO_DATA;
370			sc->sc_want =  mtod(m, hci_scodata_hdr_t *)->length;
371			break;
372
373		case BT3C_RECV_EVENT_HDR:	/* Got Event Header */
374			sc->sc_state = BT3C_RECV_EVENT_DATA;
375			sc->sc_want =  mtod(m, hci_event_hdr_t *)->length;
376			break;
377
378		case BT3C_RECV_ACL_DATA:	/* ACL Packet Complete */
379			hci_input_acl(&sc->sc_unit, sc->sc_rxp);
380			sc->sc_unit.hci_stats.acl_rx++;
381			sc->sc_rxp = m = NULL;
382			space = 0;
383			break;
384
385		case BT3C_RECV_SCO_DATA:	/* SCO Packet Complete */
386			hci_input_sco(&sc->sc_unit, sc->sc_rxp);
387			sc->sc_unit.hci_stats.sco_rx++;
388			sc->sc_rxp = m = NULL;
389			space = 0;
390			break;
391
392		case BT3C_RECV_EVENT_DATA:	/* Event Packet Complete */
393			sc->sc_unit.hci_stats.evt_rx++;
394			hci_input_event(&sc->sc_unit, sc->sc_rxp);
395			sc->sc_rxp = m = NULL;
396			space = 0;
397			break;
398
399		default:
400			panic("%s: invalid state %d!\n",
401				sc->sc_dev.dv_xname, sc->sc_state);
402		}
403	}
404
405out:
406	bt3c_write(sc, BT3C_RX_COUNT, 0x0000);
407}
408
409/*
410 * write data from current packet to Transmit FIFO.
411 * restart when done.
412 */
413static void
414bt3c_transmit(struct bt3c_softc *sc)
415{
416	struct mbuf *m;
417	int count, rlen;
418	uint8_t *rptr;
419
420	m = sc->sc_txp;
421	if (m == NULL) {
422		sc->sc_unit.hci_flags &= ~BTF_XMIT;
423		bt3c_start(&sc->sc_unit);
424		return;
425	}
426
427	count = 0;
428	rlen = 0;
429	rptr = mtod(m, uint8_t *);
430
431	bt3c_set_address(sc, BT3C_TX_FIFO);
432
433	for(;;) {
434		if (rlen >= m->m_len) {
435			m = m->m_next;
436			if (m == NULL) {
437				m = sc->sc_txp;
438				sc->sc_txp = NULL;
439
440				if (M_GETCTX(m, void *) == NULL)
441					m_freem(m);
442				else
443					hci_complete_sco(&sc->sc_unit, m);
444
445				break;
446			}
447
448			rlen = 0;
449			rptr = mtod(m, uint8_t *);
450			continue;
451		}
452
453		if (count >= BT3C_FIFO_SIZE) {
454			m_adj(m, rlen);
455			break;
456		}
457
458		bt3c_put(sc, *rptr++);
459		rlen++;
460		count++;
461	}
462
463	bt3c_write(sc, BT3C_TX_COUNT, count);
464	sc->sc_unit.hci_stats.byte_tx += count;
465}
466
467/*
468 * interrupt routine
469 */
470static int
471bt3c_intr(void *arg)
472{
473	struct bt3c_softc *sc = arg;
474	uint16_t control, isr;
475
476	control = bt3c_read_control(sc);
477	if (control & BT3C_IOR_CNTL_INTR) {
478		isr = bt3c_read(sc, BT3C_ISR);
479		if ((isr & 0xff) == 0x7f) {
480			printf("%s: bt3c_intr got strange ISR=%04x\n",
481				sc->sc_dev.dv_xname, isr);
482		} else if ((isr & 0xff) != 0xff) {
483
484			if (isr & BT3C_ISR_RXRDY)
485				bt3c_receive(sc);
486
487			if (isr & BT3C_ISR_TXRDY)
488				bt3c_transmit(sc);
489
490#ifdef DIAGNOSTIC
491			if (isr & BT3C_ISR_ANTENNA) {
492				if (bt3c_read(sc, BT3C_CSR) & BT3C_CSR_ANTENNA)
493					printf("%s: Antenna Out\n",
494						sc->sc_dev.dv_xname);
495				else
496					printf("%s: Antenna In\n",
497						sc->sc_dev.dv_xname);
498			}
499#endif
500
501			bt3c_write(sc, BT3C_ISR, 0x0000);
502			bt3c_write_control(sc, control);
503
504			return 1; /* handled */
505		}
506	}
507
508	return 0; /* not handled */
509}
510
511/*
512 * load firmware for the device
513 *
514 * The firmware file is a plain ASCII file containing lines in the format:
515 *
516 *	S<Digit><Len><Address><Data1><Data2>...<DataN><Checksum>
517 *
518 * <Digit>:	0	start ?
519 *		3	data line
520 *		7	finish ?
521 *
522 * <Len>:	1 byte, and is the number of bytes in the rest of the line
523 * <Address>:	4 byte address (only 2 bytes are valid for bt3c I think)
524 * <Data>:	2 byte data word to be written to the address
525 * <Checksum>:	checksum of all bytes in the line including <Len>
526 *
527 * all bytes are in hexadecimal
528 */
529static inline int32_t
530hex(const uint8_t *p, int n)
531{
532	uint32_t val = 0;
533
534	while (n > 0) {
535		val <<= 4;
536
537		if ('0' <= *p && *p <= '9')
538			val += (*p - '0');
539		else if ('a' <= *p && *p <= 'f')
540			val += (*p - 'a' + 0xa);
541		else if ('A' <= *p && *p <= 'F')
542			val += (*p - 'A' + 0xa);
543		else
544			return -1;
545
546		p++;
547		n--;
548	}
549
550	return val;
551}
552
553static int
554bt3c_load_firmware(struct bt3c_softc *sc)
555{
556	uint8_t *buf, *line, *next, *p;
557	int32_t addr, data;
558	int err, sum, len;
559	firmware_handle_t fh;
560	size_t size;
561
562	err = firmware_open(sc->sc_dev.dv_cfdata->cf_name,
563			    BT3C_FIRMWARE_FILE, &fh);
564	if (err) {
565		printf("%s: Cannot open firmware %s/%s\n", sc->sc_dev.dv_xname,
566		    sc->sc_dev.dv_cfdata->cf_name, BT3C_FIRMWARE_FILE);
567		return err;
568	}
569
570	size = (size_t)firmware_get_size(fh);
571#ifdef DIAGNOSTIC
572	if (size < 0 || size > 10 * 1024) {	/* sanity check */
573		printf("%s: firmware file seems WAY too big!\n",
574			sc->sc_dev.dv_xname);
575		return EFBIG;
576	}
577#endif
578
579	buf = firmware_malloc(size);
580	KASSERT(buf != NULL);
581
582	err = firmware_read(fh, 0, buf, size);
583	if (err) {
584		printf("%s: Firmware read failed (%d)\n",
585				sc->sc_dev.dv_xname, err);
586		goto out;
587	}
588
589	/* Reset */
590	bt3c_write(sc, 0x8040, 0x0404);
591	bt3c_write(sc, 0x8040, 0x0400);
592	DELAY(1);
593	bt3c_write(sc, 0x8040, 0x0404);
594	DELAY(17);
595
596	next = buf;
597	err = EFTYPE;
598
599	while (next < buf + size) {
600		line = next;
601
602		while (*next != '\r' && *next != '\n') {
603			if (next >= buf + size)
604				goto out;
605
606			next++;
607		}
608
609		/* 14 covers address and checksum minimum */
610		if (next - line < 14)
611			goto out;
612
613		if (line[0] != 'S')
614			goto out;
615
616		/* verify line length */
617		len = hex(line + 2, 2);
618		if (len < 0 || next - line != len * 2 + 4)
619			goto out;
620
621		/* checksum the line */
622		sum = 0;
623		for (p = line + 2 ; p < next ; p += 2)
624			sum += hex(p, 2);
625
626		if ((sum & 0xff) != 0xff)
627			goto out;
628
629		/* extract relevant data */
630		switch (line[1]) {
631		case '0':
632			/* I dont know what this is */
633			break;
634
635		case '3':
636			/* find number of data words */
637			len = (len - 5) / 2;
638			if (len > 15)
639				goto out;
640
641			addr = hex(line + 8, 4);
642			if (addr < 0)
643				goto out;
644
645			bt3c_set_address(sc, addr);
646
647			for (p = line + 12 ; p + 4 < next ; p += 4) {
648				data = hex(p, 4);
649				if (data < 0)
650					goto out;
651
652				bt3c_put(sc, data);
653			}
654			break;
655
656		case '7':
657			/* I dont know what this is */
658			break;
659
660		default:
661			goto out;
662		}
663
664		/* skip to start of next line */
665		while (next < buf + size && (*next == '\r' || *next == '\n'))
666			next++;
667	}
668
669	err = 0;
670	DELAY(17);
671
672	/* Boot */
673	bt3c_set_address(sc, 0x3000);
674	bt3c_write_control(sc, (bt3c_read_control(sc) | BT3C_IOR_CNTL_BOOT));
675	DELAY(17);
676
677	/* Clear Registers */
678	bt3c_write(sc, BT3C_RX_COUNT, 0x0000);
679	bt3c_write(sc, BT3C_TX_COUNT, 0x0000);
680	bt3c_write(sc, BT3C_ISR, 0x0000);
681	DELAY(1000);
682
683out:
684	firmware_free(buf, size);
685	firmware_close(fh);
686	return err;
687}
688
689/**************************************************************************
690 *
691 *  bt device callbacks (all called at IPL_TTY)
692 */
693
694/*
695 * start sending on bt3c
696 * this should be called only when BTF_XMIT is not set, and
697 * we only send cmd packets that are clear to send
698 */
699static void
700bt3c_start(struct hci_unit *unit)
701{
702	struct bt3c_softc *sc = unit->hci_softc;
703	struct mbuf *m;
704
705	KASSERT((unit->hci_flags & BTF_XMIT) == 0);
706	KASSERT(sc->sc_txp == NULL);
707
708	if (MBUFQ_FIRST(&unit->hci_cmdq)) {
709		MBUFQ_DEQUEUE(&unit->hci_cmdq, m);
710		unit->hci_stats.cmd_tx++;
711		M_SETCTX(m, NULL);
712		goto start;
713	}
714
715	if (MBUFQ_FIRST(&unit->hci_scotxq)) {
716		MBUFQ_DEQUEUE(&unit->hci_scotxq, m);
717		unit->hci_stats.sco_tx++;
718		goto start;
719	}
720
721	if (MBUFQ_FIRST(&unit->hci_acltxq)) {
722		MBUFQ_DEQUEUE(&unit->hci_acltxq, m);
723		unit->hci_stats.acl_tx++;
724		M_SETCTX(m, NULL);
725		goto start;
726	}
727
728	/* Nothing to send */
729	return;
730
731start:
732	sc->sc_txp = m;
733	unit->hci_flags |= BTF_XMIT;
734	bt3c_transmit(sc);
735}
736
737/*
738 * enable device
739 *	turn on card
740 *	load firmware
741 *	establish interrupts
742 */
743static int
744bt3c_enable(struct hci_unit *unit)
745{
746	struct bt3c_softc *sc = unit->hci_softc;
747	int err;
748
749	if (unit->hci_flags & BTF_RUNNING)
750		return 0;
751
752	sc->sc_intr = pcmcia_intr_establish(sc->sc_pf, IPL_TTY, bt3c_intr, sc);
753	if (sc->sc_intr == NULL) {
754		err = EIO;
755		goto bad;
756	}
757
758	err = pcmcia_function_enable(sc->sc_pf);
759	if (err)
760		goto bad1;
761
762	err = bt3c_load_firmware(sc);
763	if (err)
764		goto bad2;
765
766	unit->hci_flags |= BTF_RUNNING;
767	unit->hci_flags &= ~BTF_XMIT;
768
769	/*
770	 * 3Com card will send a Command_Status packet when its
771	 * ready to receive commands
772	 */
773	unit->hci_num_cmd_pkts = 0;
774
775	return 0;
776
777bad2:
778	pcmcia_function_disable(sc->sc_pf);
779bad1:
780	pcmcia_intr_disestablish(sc->sc_pf, sc->sc_intr);
781	sc->sc_intr = NULL;
782bad:
783	return err;
784}
785
786/*
787 * disable device
788 *	shut down card
789 *	disestablish interrupts
790 *	free held packets
791 */
792static void
793bt3c_disable(struct hci_unit *unit)
794{
795	struct bt3c_softc *sc = unit->hci_softc;
796
797	if ((unit->hci_flags & BTF_RUNNING) == 0)
798		return;
799
800	pcmcia_function_disable(sc->sc_pf);
801
802	if (sc->sc_intr) {
803		pcmcia_intr_disestablish(sc->sc_pf, sc->sc_intr);
804		sc->sc_intr = NULL;
805	}
806
807	if (sc->sc_rxp) {
808		m_freem(sc->sc_rxp);
809		sc->sc_rxp = NULL;
810	}
811
812	if (sc->sc_txp) {
813		m_freem(sc->sc_txp);
814		sc->sc_txp = NULL;
815	}
816
817	unit->hci_flags &= ~BTF_RUNNING;
818}
819
820/**************************************************************************
821 *
822 *	bt3c PCMCIA autoconfig glue
823 */
824
825static int
826bt3c_match(struct device *parent, struct cfdata *match, void *aux)
827{
828	struct pcmcia_attach_args *pa = aux;
829
830	if (pa->manufacturer == PCMCIA_VENDOR_3COM &&
831	    pa->product == PCMCIA_PRODUCT_3COM_3CRWB6096)
832	    return 10;		/* 'com' also claims this, so trump them */
833
834	return 0;
835}
836
837static void
838bt3c_attach(struct device *parent, struct device *self, void *aux)
839{
840	struct bt3c_softc *sc = (struct bt3c_softc *)self;
841	struct pcmcia_attach_args *pa = aux;
842	struct pcmcia_config_entry *cfe;
843
844	sc->sc_pf = pa->pf;
845
846	/* Find a PCMCIA config entry we can use */
847	SIMPLEQ_FOREACH(cfe, &pa->pf->cfe_head, cfe_list) {
848		if (cfe->num_memspace != 0)
849			continue;
850
851		if (cfe->num_iospace != 1)
852			continue;
853
854		if (pcmcia_io_alloc(pa->pf, cfe->iospace[0].start,
855				cfe->iospace[0].length, 0, &sc->sc_pcioh) == 0)
856			break;
857	}
858
859	if (cfe == 0) {
860		aprint_error("bt3c_attach: cannot allocate io space\n");
861		goto no_config_entry;
862	}
863
864	/* Initialise it */
865	pcmcia_function_init(pa->pf, cfe);
866
867	/* Map in the io space */
868	if (pcmcia_io_map(pa->pf, PCMCIA_WIDTH_AUTO,
869			&sc->sc_pcioh, &sc->sc_iow)) {
870		aprint_error("bt3c_attach: cannot map io space\n");
871		goto iomap_failed;
872	}
873
874	/* Attach Bluetooth unit */
875	sc->sc_unit.hci_softc = sc;
876	sc->sc_unit.hci_devname = sc->sc_dev.dv_xname;
877	sc->sc_unit.hci_enable = bt3c_enable;
878	sc->sc_unit.hci_disable = bt3c_disable;
879	sc->sc_unit.hci_start_cmd = bt3c_start;
880	sc->sc_unit.hci_start_acl = bt3c_start;
881	sc->sc_unit.hci_start_sco = bt3c_start;
882	sc->sc_unit.hci_ipl = IPL_TTY;
883	hci_attach(&sc->sc_unit);
884
885	/* establish a power change hook */
886	sc->sc_powerhook = powerhook_establish(bt3c_power, sc);
887	return;
888
889iomap_failed:
890	/* unmap io space */
891	pcmcia_io_free(pa->pf, &sc->sc_pcioh);
892
893no_config_entry:
894	sc->sc_iow = -1;
895}
896
897static int
898bt3c_detach(struct device *self, int flags)
899{
900	struct bt3c_softc *sc = (struct bt3c_softc *)self;
901	int err = 0;
902
903	bt3c_disable(&sc->sc_unit);
904
905	if (sc->sc_powerhook) {
906		powerhook_disestablish(sc->sc_powerhook);
907		sc->sc_powerhook = NULL;
908	}
909
910	hci_detach(&sc->sc_unit);
911
912	if (sc->sc_iow != -1) {
913		pcmcia_io_unmap(sc->sc_pf, sc->sc_iow);
914		pcmcia_io_free(sc->sc_pf, &sc->sc_pcioh);
915		sc->sc_iow = -1;
916	}
917
918	return err;
919}
920
921static int
922bt3c_activate(struct device *self, enum devact act)
923{
924	// struct bt3c_softc *sc = (struct bt3c_softc *)self;
925	int err = 0;
926
927	switch(act) {
928	case DVACT_ACTIVATE:
929		err = EOPNOTSUPP;
930		break;
931
932	case DVACT_DEACTIVATE:
933		// could notify unit somehow?
934		break;
935	}
936
937	return err;
938}
939
940static void
941bt3c_power(int why, void *arg)
942{
943	struct bt3c_softc *sc = arg;
944
945	switch(why) {
946	case PWR_SUSPEND:
947	case PWR_STANDBY:
948		if (sc->sc_unit.hci_flags & BTF_RUNNING) {
949			hci_detach(&sc->sc_unit);
950
951			sc->sc_flags |= BT3C_SLEEPING;
952			printf_nolog("%s: sleeping\n", sc->sc_dev.dv_xname);
953		}
954		break;
955
956	case PWR_RESUME:
957		if (sc->sc_flags & BT3C_SLEEPING) {
958			printf_nolog("%s: waking up\n", sc->sc_dev.dv_xname);
959			sc->sc_flags &= ~BT3C_SLEEPING;
960
961			memset(&sc->sc_unit, 0, sizeof(sc->sc_unit));
962			sc->sc_unit.hci_softc = sc;
963			sc->sc_unit.hci_devname = sc->sc_dev.dv_xname;
964			sc->sc_unit.hci_enable = bt3c_enable;
965			sc->sc_unit.hci_disable = bt3c_disable;
966			sc->sc_unit.hci_start_cmd = bt3c_start;
967			sc->sc_unit.hci_start_acl = bt3c_start;
968			sc->sc_unit.hci_start_sco = bt3c_start;
969			sc->sc_unit.hci_ipl = IPL_TTY;
970			hci_attach(&sc->sc_unit);
971		}
972		break;
973
974	case PWR_SOFTSUSPEND:
975	case PWR_SOFTSTANDBY:
976	case PWR_SOFTRESUME:
977		break;
978	}
979}
980