xref: /netbsd-src/sys/dev/pcmcia/bt3c.c (revision 7fa608457b817eca6e0977b37f758ae064f3c99c)
1 /* $NetBSD: bt3c.c,v 1.15 2007/11/11 12:59:02 plunky 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.15 2007/11/11 12:59:02 plunky 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 <sys/cpu.h>
80 #include <sys/bus.h>
81 #include <sys/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 
98 struct bt3c_softc {
99 	device_t	sc_dev;
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 
129 static int bt3c_match(device_t, struct cfdata *, void *);
130 static void bt3c_attach(device_t, device_t, void *);
131 static int bt3c_detach(device_t, int);
132 static void bt3c_power(int, void *);
133 
134 CFATTACH_DECL_NEW(bt3c, sizeof(struct bt3c_softc),
135     bt3c_match, bt3c_attach, bt3c_detach, NULL);
136 
137 static void bt3c_start(device_t);
138 static int bt3c_enable(device_t);
139 static void bt3c_disable(device_t);
140 
141 /**************************************************************************
142  *
143  *	Hardware Definitions & IO routines
144  *
145  *	I made up the names for most of these defs since we dont have
146  *	manufacturers recommendations, but I dont like raw numbers..
147  *
148  *	all hardware routines are running at IPL_TTY
149  *
150  */
151 #define BT3C_ISR		0x7001		/* Interrupt Status Register */
152 #define BT3C_ISR_RXRDY			(1<<0)	/* Device has data */
153 #define BT3C_ISR_TXRDY			(1<<1)	/* Finished sending data */
154 #define BT3C_ISR_ANTENNA		(1<<5)	/* Antenna position changed */
155 
156 #define BT3C_CSR		0x7002		/* Card Status Register */
157 #define BT3C_CSR_ANTENNA		(1<<4)	/* Antenna position */
158 
159 #define BT3C_TX_COUNT		0x7005		/* Tx fifo contents */
160 #define BT3C_TX_FIFO		0x7080		/* Transmit Fifo */
161 #define BT3C_RX_COUNT		0x7006		/* Rx fifo contents */
162 #define BT3C_RX_FIFO		0x7480		/* Receive Fifo */
163 #define BT3C_FIFO_SIZE			256
164 
165 /* IO Registers */
166 #define BT3C_IOR_DATA_L		0x00		/* data low byte */
167 #define BT3C_IOR_DATA_H		0x01		/* data high byte */
168 #define BT3C_IOR_ADDR_L		0x02		/* address low byte */
169 #define BT3C_IOR_ADDR_H		0x03		/* address high byte */
170 #define BT3C_IOR_CNTL		0x04		/* control byte */
171 #define BT3C_IOR_CNTL_BOOT		(1<<6)	/* Boot Card */
172 #define BT3C_IOR_CNTL_INTR		(1<<7)	/* Interrupt Requested */
173 #define BT3C_IOR_LEN		0x05
174 
175 static inline uint16_t
176 bt3c_get(struct bt3c_softc *sc)
177 {
178 	uint16_t data;
179 
180 	bus_space_barrier(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
181 				0, BT3C_IOR_LEN, BUS_SPACE_BARRIER_READ);
182 	data = bus_space_read_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
183 				BT3C_IOR_DATA_L);
184 	data |= bus_space_read_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
185 				BT3C_IOR_DATA_H) << 8;
186 
187 	return data;
188 }
189 
190 static inline void
191 bt3c_put(struct bt3c_softc *sc, uint16_t data)
192 {
193 
194 	bus_space_barrier(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
195 			0, BT3C_IOR_LEN, BUS_SPACE_BARRIER_WRITE);
196 	bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
197 			BT3C_IOR_DATA_L, data & 0xff);
198 	bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
199 			BT3C_IOR_DATA_H, (data >> 8) & 0xff);
200 }
201 
202 static inline uint8_t
203 bt3c_read_control(struct bt3c_softc *sc)
204 {
205 
206 	bus_space_barrier(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
207 			0, BT3C_IOR_LEN, BUS_SPACE_BARRIER_READ);
208 	return bus_space_read_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
209 			BT3C_IOR_CNTL);
210 }
211 
212 static inline void
213 bt3c_write_control(struct bt3c_softc *sc, uint8_t data)
214 {
215 
216 	bus_space_barrier(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
217 			0, BT3C_IOR_LEN, BUS_SPACE_BARRIER_WRITE);
218 	bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
219 			BT3C_IOR_CNTL, data);
220 }
221 
222 static inline void
223 bt3c_set_address(struct bt3c_softc *sc, uint16_t addr)
224 {
225 
226 	bus_space_barrier(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
227 			0, BT3C_IOR_LEN, BUS_SPACE_BARRIER_WRITE);
228 	bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
229 			BT3C_IOR_ADDR_L, addr & 0xff);
230 	bus_space_write_1(sc->sc_pcioh.iot, sc->sc_pcioh.ioh,
231 			BT3C_IOR_ADDR_H, (addr >> 8) & 0xff);
232 }
233 
234 static inline uint16_t
235 bt3c_read(struct bt3c_softc *sc, uint16_t addr)
236 {
237 
238 	bt3c_set_address(sc, addr);
239 	return bt3c_get(sc);
240 }
241 
242 static inline void
243 bt3c_write(struct bt3c_softc *sc, uint16_t addr, uint16_t data)
244 {
245 
246 	bt3c_set_address(sc, addr);
247 	bt3c_put(sc, data);
248 }
249 
250 /*
251  * receive incoming data from device, store in mbuf chain and
252  * pass on complete packets to bt device
253  */
254 static void
255 bt3c_receive(struct bt3c_softc *sc)
256 {
257 	struct mbuf *m = sc->sc_rxp;
258 	int space = 0;
259 	uint16_t count;
260 	uint8_t b;
261 
262 	/*
263 	 * If we already started a packet, find the
264 	 * trailing end of it.
265 	 */
266 	if (m) {
267 		while (m->m_next)
268 			m = m->m_next;
269 
270 		space = M_TRAILINGSPACE(m);
271 	}
272 
273 	count = bt3c_read(sc, BT3C_RX_COUNT);
274 	bt3c_set_address(sc, BT3C_RX_FIFO);
275 
276 	while (count > 0) {
277 		if (space == 0) {
278 			if (m == NULL) {
279 				/* new packet */
280 				MGETHDR(m, M_DONTWAIT, MT_DATA);
281 				if (m == NULL) {
282 					aprint_error_dev(sc->sc_dev,
283 					    "out of memory\n");
284 					++sc->sc_unit.hci_stats.err_rx;
285 					goto out;	/* (lost sync) */
286 				}
287 
288 				sc->sc_rxp = m;
289 				m->m_pkthdr.len = m->m_len = 0;
290 				space = MHLEN;
291 
292 				sc->sc_state = BT3C_RECV_PKT_TYPE;
293 				sc->sc_want = 1;
294 			} else {
295 				/* extend mbuf */
296 				MGET(m->m_next, M_DONTWAIT, MT_DATA);
297 				if (m->m_next == NULL) {
298 					aprint_error_dev(sc->sc_dev,
299 					    "out of memory\n");
300 					++sc->sc_unit.hci_stats.err_rx;
301 					goto out;	/* (lost sync) */
302 				}
303 
304 				m = m->m_next;
305 				m->m_len = 0;
306 				space = MLEN;
307 
308 				if (sc->sc_want > MINCLSIZE) {
309 					MCLGET(m, M_DONTWAIT);
310 					if (m->m_flags & M_EXT)
311 						space = MCLBYTES;
312 				}
313 			}
314 		}
315 
316 		b = bt3c_get(sc);
317 		mtod(m, uint8_t *)[m->m_len++] = b;
318 		count--;
319 		space--;
320 		sc->sc_rxp->m_pkthdr.len++;
321 		sc->sc_unit.hci_stats.byte_rx++;
322 
323 		sc->sc_want--;
324 		if (sc->sc_want > 0)
325 			continue; /* want more */
326 
327 		switch (sc->sc_state) {
328 		case BT3C_RECV_PKT_TYPE:		/* Got packet type */
329 
330 			switch (b) {
331 			case HCI_ACL_DATA_PKT:
332 				sc->sc_state = BT3C_RECV_ACL_HDR;
333 				sc->sc_want = sizeof(hci_acldata_hdr_t) - 1;
334 				break;
335 
336 			case HCI_SCO_DATA_PKT:
337 				sc->sc_state = BT3C_RECV_SCO_HDR;
338 				sc->sc_want = sizeof(hci_scodata_hdr_t) - 1;
339 				break;
340 
341 			case HCI_EVENT_PKT:
342 				sc->sc_state = BT3C_RECV_EVENT_HDR;
343 				sc->sc_want = sizeof(hci_event_hdr_t) - 1;
344 				break;
345 
346 			default:
347 				aprint_error_dev(sc->sc_dev,
348 				    "Unknown packet type=%#x!\n", b);
349 				++sc->sc_unit.hci_stats.err_rx;
350 				m_freem(sc->sc_rxp);
351 				sc->sc_rxp = NULL;
352 				goto out;	/* (lost sync) */
353 			}
354 
355 			break;
356 
357 		/*
358 		 * we assume (correctly of course :) that the packet headers
359 		 * all fit into a single pkthdr mbuf
360 		 */
361 		case BT3C_RECV_ACL_HDR:		/* Got ACL Header */
362 			sc->sc_state = BT3C_RECV_ACL_DATA;
363 			sc->sc_want = mtod(m, hci_acldata_hdr_t *)->length;
364 			sc->sc_want = le16toh(sc->sc_want);
365 			break;
366 
367 		case BT3C_RECV_SCO_HDR:		/* Got SCO Header */
368 			sc->sc_state = BT3C_RECV_SCO_DATA;
369 			sc->sc_want =  mtod(m, hci_scodata_hdr_t *)->length;
370 			break;
371 
372 		case BT3C_RECV_EVENT_HDR:	/* Got Event Header */
373 			sc->sc_state = BT3C_RECV_EVENT_DATA;
374 			sc->sc_want =  mtod(m, hci_event_hdr_t *)->length;
375 			break;
376 
377 		case BT3C_RECV_ACL_DATA:	/* ACL Packet Complete */
378 			hci_input_acl(&sc->sc_unit, sc->sc_rxp);
379 			sc->sc_unit.hci_stats.acl_rx++;
380 			sc->sc_rxp = m = NULL;
381 			space = 0;
382 			break;
383 
384 		case BT3C_RECV_SCO_DATA:	/* SCO Packet Complete */
385 			hci_input_sco(&sc->sc_unit, sc->sc_rxp);
386 			sc->sc_unit.hci_stats.sco_rx++;
387 			sc->sc_rxp = m = NULL;
388 			space = 0;
389 			break;
390 
391 		case BT3C_RECV_EVENT_DATA:	/* Event Packet Complete */
392 			sc->sc_unit.hci_stats.evt_rx++;
393 			hci_input_event(&sc->sc_unit, sc->sc_rxp);
394 			sc->sc_rxp = m = NULL;
395 			space = 0;
396 			break;
397 
398 		default:
399 			panic("%s: invalid state %d!\n",
400 				device_xname(sc->sc_dev), sc->sc_state);
401 		}
402 	}
403 
404 out:
405 	bt3c_write(sc, BT3C_RX_COUNT, 0x0000);
406 }
407 
408 /*
409  * write data from current packet to Transmit FIFO.
410  * restart when done.
411  */
412 static void
413 bt3c_transmit(struct bt3c_softc *sc)
414 {
415 	struct mbuf *m;
416 	int count, rlen;
417 	uint8_t *rptr;
418 
419 	m = sc->sc_txp;
420 	if (m == NULL) {
421 		sc->sc_unit.hci_flags &= ~BTF_XMIT;
422 		bt3c_start(sc->sc_dev);
423 		return;
424 	}
425 
426 	count = 0;
427 	rlen = 0;
428 	rptr = mtod(m, uint8_t *);
429 
430 	bt3c_set_address(sc, BT3C_TX_FIFO);
431 
432 	for(;;) {
433 		if (rlen >= m->m_len) {
434 			m = m->m_next;
435 			if (m == NULL) {
436 				m = sc->sc_txp;
437 				sc->sc_txp = NULL;
438 
439 				if (M_GETCTX(m, void *) == NULL)
440 					m_freem(m);
441 				else
442 					hci_complete_sco(&sc->sc_unit, m);
443 
444 				break;
445 			}
446 
447 			rlen = 0;
448 			rptr = mtod(m, uint8_t *);
449 			continue;
450 		}
451 
452 		if (count >= BT3C_FIFO_SIZE) {
453 			m_adj(m, rlen);
454 			break;
455 		}
456 
457 		bt3c_put(sc, *rptr++);
458 		rlen++;
459 		count++;
460 	}
461 
462 	bt3c_write(sc, BT3C_TX_COUNT, count);
463 	sc->sc_unit.hci_stats.byte_tx += count;
464 }
465 
466 /*
467  * interrupt routine
468  */
469 static int
470 bt3c_intr(void *arg)
471 {
472 	struct bt3c_softc *sc = arg;
473 	uint16_t control, isr;
474 
475 	control = bt3c_read_control(sc);
476 	if (control & BT3C_IOR_CNTL_INTR) {
477 		isr = bt3c_read(sc, BT3C_ISR);
478 		if ((isr & 0xff) == 0x7f) {
479 			aprint_error_dev(sc->sc_dev, "strange ISR=%04x\n", isr);
480 		} else if ((isr & 0xff) != 0xff) {
481 
482 			if (isr & BT3C_ISR_RXRDY)
483 				bt3c_receive(sc);
484 
485 			if (isr & BT3C_ISR_TXRDY)
486 				bt3c_transmit(sc);
487 
488 #ifdef DIAGNOSTIC
489 			if (isr & BT3C_ISR_ANTENNA) {
490 				if (bt3c_read(sc, BT3C_CSR) & BT3C_CSR_ANTENNA)
491 					aprint_verbose_dev(sc->sc_dev,
492 					    "Antenna Out\n");
493 				else
494 					aprint_verbose_dev(sc->sc_dev,
495 					    "Antenna In\n");
496 			}
497 #endif
498 
499 			bt3c_write(sc, BT3C_ISR, 0x0000);
500 			bt3c_write_control(sc, control);
501 
502 			return 1; /* handled */
503 		}
504 	}
505 
506 	return 0; /* not handled */
507 }
508 
509 /*
510  * load firmware for the device
511  *
512  * The firmware file is a plain ASCII file in the Motorola S-Record format,
513  * with lines in the format:
514  *
515  *	S<Digit><Len><Address><Data1><Data2>...<DataN><Checksum>
516  *
517  * <Digit>:	0	header
518  *		3	data record (4 byte address)
519  *		7	boot record (4 byte address)
520  *
521  * <Len>:	1 byte, and is the number of bytes in the rest of the line
522  * <Address>:	4 byte address (only 2 bytes are valid for bt3c I think)
523  * <Data>:	2 byte data word to be written to the address
524  * <Checksum>:	checksum of all bytes in the line including <Len>
525  *
526  * all bytes are in hexadecimal
527  */
528 static inline int32_t
529 hex(const uint8_t *p, int n)
530 {
531 	uint32_t val = 0;
532 
533 	while (n > 0) {
534 		val <<= 4;
535 
536 		if ('0' <= *p && *p <= '9')
537 			val += (*p - '0');
538 		else if ('a' <= *p && *p <= 'f')
539 			val += (*p - 'a' + 0xa);
540 		else if ('A' <= *p && *p <= 'F')
541 			val += (*p - 'A' + 0xa);
542 		else
543 			return -1;
544 
545 		p++;
546 		n--;
547 	}
548 
549 	return val;
550 }
551 
552 static int
553 bt3c_load_firmware(struct bt3c_softc *sc)
554 {
555 	uint8_t *buf, *line, *next, *p;
556 	int32_t addr, data;
557 	int err, sum, len;
558 	firmware_handle_t fh;
559 	struct cfdata *cf = device_cfdata(sc->sc_dev);
560 	size_t size;
561 
562 	err = firmware_open(cf->cf_name,
563 			    BT3C_FIRMWARE_FILE, &fh);
564 	if (err) {
565 		aprint_error_dev(sc->sc_dev, "Cannot open firmware %s/%s\n",
566 		    cf->cf_name, BT3C_FIRMWARE_FILE);
567 		return err;
568 	}
569 
570 	size = (size_t)firmware_get_size(fh);
571 #ifdef DIAGNOSTIC
572 	if (size > 10 * 1024) {	/* sanity check */
573 		aprint_error_dev(sc->sc_dev, "insane firmware file size!\n");
574 		firmware_close(fh);
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 		aprint_error_dev(sc->sc_dev, "Firmware read failed (%d)\n", err);
585 		goto out;
586 	}
587 
588 	/* Reset */
589 	bt3c_write(sc, 0x8040, 0x0404);
590 	bt3c_write(sc, 0x8040, 0x0400);
591 	DELAY(1);
592 	bt3c_write(sc, 0x8040, 0x0404);
593 	DELAY(17);
594 
595 	next = buf;
596 	err = EFTYPE;
597 
598 	while (next < buf + size) {
599 		line = next;
600 
601 		while (*next != '\r' && *next != '\n') {
602 			if (next >= buf + size)
603 				goto out;
604 
605 			next++;
606 		}
607 
608 		/* 14 covers address and checksum minimum */
609 		if (next - line < 14)
610 			goto out;
611 
612 		if (line[0] != 'S')
613 			goto out;
614 
615 		/* verify line length */
616 		len = hex(line + 2, 2);
617 		if (len < 0 || next - line != len * 2 + 4)
618 			goto out;
619 
620 		/* checksum the line */
621 		sum = 0;
622 		for (p = line + 2 ; p < next ; p += 2)
623 			sum += hex(p, 2);
624 
625 		if ((sum & 0xff) != 0xff)
626 			goto out;
627 
628 		/* extract relevant data */
629 		switch (line[1]) {
630 		case '0':
631 			/* we ignore the header */
632 			break;
633 
634 		case '3':
635 			/* find number of data words */
636 			len = (len - 5) / 2;
637 			if (len > 15)
638 				goto out;
639 
640 			addr = hex(line + 8, 4);
641 			if (addr < 0)
642 				goto out;
643 
644 			bt3c_set_address(sc, addr);
645 
646 			for (p = line + 12 ; p + 4 < next ; p += 4) {
647 				data = hex(p, 4);
648 				if (data < 0)
649 					goto out;
650 
651 				bt3c_put(sc, data);
652 			}
653 			break;
654 
655 		case '7':
656 			/*
657 			 * for some reason we ignore this record
658 			 * and boot from 0x3000 which happens to
659 			 * be the first record in the file.
660 			 */
661 			break;
662 
663 		default:
664 			goto out;
665 		}
666 
667 		/* skip to start of next line */
668 		while (next < buf + size && (*next == '\r' || *next == '\n'))
669 			next++;
670 	}
671 
672 	err = 0;
673 	DELAY(17);
674 
675 	/* Boot */
676 	bt3c_set_address(sc, 0x3000);
677 	bt3c_write_control(sc, (bt3c_read_control(sc) | BT3C_IOR_CNTL_BOOT));
678 	DELAY(17);
679 
680 	/* Clear Registers */
681 	bt3c_write(sc, BT3C_RX_COUNT, 0x0000);
682 	bt3c_write(sc, BT3C_TX_COUNT, 0x0000);
683 	bt3c_write(sc, BT3C_ISR, 0x0000);
684 	DELAY(1000);
685 
686 out:
687 	firmware_free(buf, size);
688 	firmware_close(fh);
689 	return err;
690 }
691 
692 /**************************************************************************
693  *
694  *  bt device callbacks (all called at IPL_TTY)
695  */
696 
697 /*
698  * start sending on bt3c
699  * this should be called only when BTF_XMIT is not set, and
700  * we only send cmd packets that are clear to send
701  */
702 static void
703 bt3c_start(device_t self)
704 {
705 	struct bt3c_softc *sc = device_private(self);
706 	struct hci_unit *unit = &sc->sc_unit;
707 	struct mbuf *m;
708 
709 	KASSERT((unit->hci_flags & BTF_XMIT) == 0);
710 	KASSERT(sc->sc_txp == NULL);
711 
712 	if (MBUFQ_FIRST(&unit->hci_cmdq)) {
713 		MBUFQ_DEQUEUE(&unit->hci_cmdq, m);
714 		unit->hci_stats.cmd_tx++;
715 		M_SETCTX(m, NULL);
716 		goto start;
717 	}
718 
719 	if (MBUFQ_FIRST(&unit->hci_scotxq)) {
720 		MBUFQ_DEQUEUE(&unit->hci_scotxq, m);
721 		unit->hci_stats.sco_tx++;
722 		goto start;
723 	}
724 
725 	if (MBUFQ_FIRST(&unit->hci_acltxq)) {
726 		MBUFQ_DEQUEUE(&unit->hci_acltxq, m);
727 		unit->hci_stats.acl_tx++;
728 		M_SETCTX(m, NULL);
729 		goto start;
730 	}
731 
732 	/* Nothing to send */
733 	return;
734 
735 start:
736 	sc->sc_txp = m;
737 	unit->hci_flags |= BTF_XMIT;
738 	bt3c_transmit(sc);
739 }
740 
741 /*
742  * enable device
743  *	turn on card
744  *	load firmware
745  *	establish interrupts
746  */
747 static int
748 bt3c_enable(device_t self)
749 {
750 	struct bt3c_softc *sc = device_private(self);
751 	struct hci_unit *unit = &sc->sc_unit;
752 	int err;
753 
754 	if (unit->hci_flags & BTF_RUNNING)
755 		return 0;
756 
757 	sc->sc_intr = pcmcia_intr_establish(sc->sc_pf, IPL_TTY, bt3c_intr, sc);
758 	if (sc->sc_intr == NULL) {
759 		err = EIO;
760 		goto bad;
761 	}
762 
763 	err = pcmcia_function_enable(sc->sc_pf);
764 	if (err)
765 		goto bad1;
766 
767 	err = bt3c_load_firmware(sc);
768 	if (err)
769 		goto bad2;
770 
771 	unit->hci_flags |= BTF_RUNNING;
772 	unit->hci_flags &= ~BTF_XMIT;
773 
774 	/*
775 	 * 3Com card will send a Command_Status packet when its
776 	 * ready to receive commands
777 	 */
778 	unit->hci_num_cmd_pkts = 0;
779 
780 	return 0;
781 
782 bad2:
783 	pcmcia_function_disable(sc->sc_pf);
784 bad1:
785 	pcmcia_intr_disestablish(sc->sc_pf, sc->sc_intr);
786 	sc->sc_intr = NULL;
787 bad:
788 	return err;
789 }
790 
791 /*
792  * disable device
793  *	shut down card
794  *	disestablish interrupts
795  *	free held packets
796  */
797 static void
798 bt3c_disable(device_t self)
799 {
800 	struct bt3c_softc *sc = device_private(self);
801 	struct hci_unit *unit = &sc->sc_unit;
802 
803 	if ((unit->hci_flags & BTF_RUNNING) == 0)
804 		return;
805 
806 	pcmcia_function_disable(sc->sc_pf);
807 
808 	if (sc->sc_intr) {
809 		pcmcia_intr_disestablish(sc->sc_pf, sc->sc_intr);
810 		sc->sc_intr = NULL;
811 	}
812 
813 	if (sc->sc_rxp) {
814 		m_freem(sc->sc_rxp);
815 		sc->sc_rxp = NULL;
816 	}
817 
818 	if (sc->sc_txp) {
819 		m_freem(sc->sc_txp);
820 		sc->sc_txp = NULL;
821 	}
822 
823 	unit->hci_flags &= ~BTF_RUNNING;
824 }
825 
826 /**************************************************************************
827  *
828  *	bt3c PCMCIA autoconfig glue
829  */
830 
831 static int
832 bt3c_match(device_t parent, struct cfdata *match, void *aux)
833 {
834 	struct pcmcia_attach_args *pa = aux;
835 
836 	if (pa->manufacturer == PCMCIA_VENDOR_3COM &&
837 	    pa->product == PCMCIA_PRODUCT_3COM_3CRWB6096)
838 	    return 10;		/* 'com' also claims this, so trump them */
839 
840 	return 0;
841 }
842 
843 static void
844 bt3c_attach(device_t parent, device_t self, void *aux)
845 {
846 	struct bt3c_softc *sc = device_private(self);
847 	struct pcmcia_attach_args *pa = aux;
848 	struct pcmcia_config_entry *cfe;
849 
850 	sc->sc_dev = self;
851 	sc->sc_pf = pa->pf;
852 
853 	/* Find a PCMCIA config entry we can use */
854 	SIMPLEQ_FOREACH(cfe, &pa->pf->cfe_head, cfe_list) {
855 		if (cfe->num_memspace != 0)
856 			continue;
857 
858 		if (cfe->num_iospace != 1)
859 			continue;
860 
861 		if (pcmcia_io_alloc(pa->pf, cfe->iospace[0].start,
862 				cfe->iospace[0].length, 0, &sc->sc_pcioh) == 0)
863 			break;
864 	}
865 
866 	if (cfe == 0) {
867 		aprint_error("bt3c_attach: cannot allocate io space\n");
868 		goto no_config_entry;
869 	}
870 
871 	/* Initialise it */
872 	pcmcia_function_init(pa->pf, cfe);
873 
874 	/* Map in the io space */
875 	if (pcmcia_io_map(pa->pf, PCMCIA_WIDTH_AUTO,
876 			&sc->sc_pcioh, &sc->sc_iow)) {
877 		aprint_error("bt3c_attach: cannot map io space\n");
878 		goto iomap_failed;
879 	}
880 
881 	/* Attach Bluetooth unit */
882 	sc->sc_unit.hci_dev = self;
883 	sc->sc_unit.hci_enable = bt3c_enable;
884 	sc->sc_unit.hci_disable = bt3c_disable;
885 	sc->sc_unit.hci_start_cmd = bt3c_start;
886 	sc->sc_unit.hci_start_acl = bt3c_start;
887 	sc->sc_unit.hci_start_sco = bt3c_start;
888 	sc->sc_unit.hci_ipl = makeiplcookie(IPL_TTY);
889 	hci_attach(&sc->sc_unit);
890 
891 	/* establish a power change hook */
892 	sc->sc_powerhook = powerhook_establish(device_xname(sc->sc_dev),
893 	    bt3c_power, sc);
894 	return;
895 
896 iomap_failed:
897 	/* unmap io space */
898 	pcmcia_io_free(pa->pf, &sc->sc_pcioh);
899 
900 no_config_entry:
901 	sc->sc_iow = -1;
902 }
903 
904 static int
905 bt3c_detach(device_t self, int flags)
906 {
907 	struct bt3c_softc *sc = device_private(self);
908 	int err = 0;
909 
910 	bt3c_disable(self);
911 
912 	if (sc->sc_powerhook) {
913 		powerhook_disestablish(sc->sc_powerhook);
914 		sc->sc_powerhook = NULL;
915 	}
916 
917 	hci_detach(&sc->sc_unit);
918 
919 	if (sc->sc_iow != -1) {
920 		pcmcia_io_unmap(sc->sc_pf, sc->sc_iow);
921 		pcmcia_io_free(sc->sc_pf, &sc->sc_pcioh);
922 		sc->sc_iow = -1;
923 	}
924 
925 	return err;
926 }
927 
928 static void
929 bt3c_power(int why, void *arg)
930 {
931 	struct bt3c_softc *sc = arg;
932 
933 	switch(why) {
934 	case PWR_SUSPEND:
935 	case PWR_STANDBY:
936 		if (sc->sc_unit.hci_flags & BTF_RUNNING) {
937 			hci_detach(&sc->sc_unit);
938 
939 			sc->sc_flags |= BT3C_SLEEPING;
940 			aprint_verbose_dev(sc->sc_dev, "sleeping\n");
941 		}
942 		break;
943 
944 	case PWR_RESUME:
945 		if (sc->sc_flags & BT3C_SLEEPING) {
946 			aprint_verbose_dev(sc->sc_dev, "waking up\n");
947 			sc->sc_flags &= ~BT3C_SLEEPING;
948 
949 			memset(&sc->sc_unit, 0, sizeof(sc->sc_unit));
950 			sc->sc_unit.hci_dev = sc->sc_dev;
951 			sc->sc_unit.hci_enable = bt3c_enable;
952 			sc->sc_unit.hci_disable = bt3c_disable;
953 			sc->sc_unit.hci_start_cmd = bt3c_start;
954 			sc->sc_unit.hci_start_acl = bt3c_start;
955 			sc->sc_unit.hci_start_sco = bt3c_start;
956 			sc->sc_unit.hci_ipl = makeiplcookie(IPL_TTY);
957 			hci_attach(&sc->sc_unit);
958 		}
959 		break;
960 
961 	case PWR_SOFTSUSPEND:
962 	case PWR_SOFTSTANDBY:
963 	case PWR_SOFTRESUME:
964 		break;
965 	}
966 }
967