xref: /netbsd-src/sys/dev/pci/oboe.c (revision 8b0f9554ff8762542c4defc4f70e1eb76fb508fa)
1 /*	$NetBSD: oboe.c,v 1.29 2007/12/15 00:39:30 perry Exp $	*/
2 
3 /*	XXXXFVDL THIS DRIVER IS BROKEN FOR NON-i386 -- vtophys() usage	*/
4 
5 /*-
6  * Copyright (c) 2001 The NetBSD Foundation, Inc.
7  * All rights reserved.
8  *
9  * This code is derived from software contributed to The NetBSD Foundation
10  * by Jan Sparud.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. All advertising materials mentioning features or use of this software
21  *    must display the following acknowledgement:
22  *	This product includes software developed by the NetBSD
23  *	Foundation, Inc. and its contributors.
24  * 4. Neither the name of The NetBSD Foundation nor the names of its
25  *    contributors may be used to endorse or promote products derived
26  *    from this software without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38  * POSSIBILITY OF SUCH DAMAGE.
39  */
40 
41 /*
42  * Toshiba OBOE IrDA SIR/FIR driver.
43  *
44  * Based on information from the Linux driver, thus the magic hex numbers.
45  */
46 
47 #include <sys/cdefs.h>
48 __KERNEL_RCSID(0, "$NetBSD: oboe.c,v 1.29 2007/12/15 00:39:30 perry Exp $");
49 
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/kernel.h>
53 #include <sys/device.h>
54 #include <sys/malloc.h>
55 #include <sys/tty.h>
56 #include <sys/vnode.h>
57 #include <sys/poll.h>
58 #include <sys/proc.h>
59 
60 #include <dev/ir/ir.h>
61 #include <dev/ir/irdaio.h>
62 #include <dev/ir/irframevar.h>
63 #include <dev/ir/sir.h>
64 
65 #include <dev/pci/pcidevs.h>
66 #include <dev/pci/pcivar.h>
67 
68 #include <sys/bus.h>
69 #include <sys/intr.h>
70 #include <uvm/uvm_extern.h>
71 
72 #include <dev/pci/oboereg.h>
73 
74 static int oboe_match(struct device *parent, struct cfdata *match, void *aux);
75 static void oboe_attach(struct device *parent, struct device *self, void *aux);
76 static int oboe_activate(struct device *self, enum devact act);
77 static int oboe_detach(struct device *self, int flags);
78 
79 static int oboe_open(void *h, int flag, int mode, struct lwp *l);
80 static int oboe_close(void *h, int flag, int mode, struct lwp *l);
81 static int oboe_read(void *h, struct uio *uio, int flag);
82 static int oboe_write(void *h, struct uio *uio, int flag);
83 static int oboe_set_params(void *h, struct irda_params *params);
84 static int oboe_get_speeds(void *h, int *speeds);
85 static int oboe_get_turnarounds(void *h, int *times);
86 static int oboe_poll(void *h, int events, struct lwp *l);
87 static int oboe_kqfilter(void *h, struct knote *kn);
88 
89 #ifdef OBOE_DEBUG
90 #define DPRINTF(x)	if (oboedebug) printf x
91 int oboedebug = 1;
92 #else
93 #define DPRINTF(x)
94 #endif
95 
96 struct oboe_dma;
97 
98 struct oboe_softc {
99 	struct device		sc_dev;
100 	struct device		*sc_child;
101 	struct pci_attach_args	sc_pa;
102 	pci_intr_handle_t *	sc_ih;
103 	unsigned int		sc_revision;	/* PCI Revision ID */
104 	/* I/O Base device */
105 	bus_space_tag_t		sc_iot;
106 	bus_space_handle_t	sc_ioh;
107 	bus_dma_tag_t		sc_dmatag;
108 	struct selinfo		sc_rsel;
109 	struct selinfo		sc_wsel;
110 
111 	int			sc_state;
112 #define	OBOE_RSLP		0x01	/* waiting for data (read) */
113 #define	OBOE_WSLP		0x02	/* waiting for data (write) */
114 #define OBOE_CLOSING		0x04	/* waiting for output to drain */
115 
116 	int			sc_speeds;
117 	int			sc_flags;
118 	int			sc_speed;
119 	int			sc_ebofs;
120 
121 	struct oboe_dma		*sc_dmas;
122 	struct OboeTaskFile	*sc_taskfile;    /* The taskfile   */
123 	u_char *		sc_xmit_bufs[TX_SLOTS];
124 	u_char *		sc_recv_bufs[RX_SLOTS];
125 	void *			sc_xmit_stores[TX_SLOTS];
126 	void *			sc_recv_stores[RX_SLOTS];
127 	int			sc_txs; /* Current transmit slot number */
128 	int			sc_rxs; /* Current receive slot number */
129 	int			sc_saved; /* number of saved frames */
130 	int			sc_lens[RX_SLOTS];
131 
132 	int			sc_txpending;
133 
134 	/* Statistics */
135 	int			sc_txpackets;
136 	int			sc_rxpackets;
137 	int			sc_txerrors;
138 	int			sc_rxerrors;
139 };
140 
141 static int oboe_intr(void *handle);
142 static int oboe_reset(struct oboe_softc *);
143 
144 struct oboe_dma {
145 	bus_dmamap_t map;
146 	void *addr;
147 	bus_dma_segment_t segs[1];
148 	int nsegs;
149 	size_t size;
150 	struct oboe_dma *next;
151 };
152 
153 #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr)
154 #define KERNADDR(p) ((void *)((p)->addr))
155 
156 static int oboe_alloc_taskfile(struct oboe_softc *);
157 static void oboe_init_taskfile(struct oboe_softc *);
158 static void oboe_startchip(struct oboe_softc *);
159 static void oboe_stopchip(struct oboe_softc *);
160 static int oboe_setbaud(struct oboe_softc *, int);
161 
162 CFATTACH_DECL(oboe, sizeof(struct oboe_softc),
163     oboe_match, oboe_attach, oboe_detach, oboe_activate);
164 
165 static struct irframe_methods oboe_methods = {
166 	oboe_open, oboe_close, oboe_read, oboe_write, oboe_poll,
167 	oboe_kqfilter, oboe_set_params, oboe_get_speeds, oboe_get_turnarounds
168 };
169 
170 static int
171 oboe_match(struct device *parent, struct cfdata *match,
172     void *aux)
173 {
174 	struct pci_attach_args *pa = aux;
175 
176 	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_TOSHIBA2 &&
177 	    (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_TOSHIBA2_OBOE ||
178 	     PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_TOSHIBA2_DONAUOBOE))
179 		return (1);
180 	return 0;
181 }
182 
183 static void
184 oboe_attach(struct device *parent, struct device *self, void *aux)
185 {
186 	struct oboe_softc *sc = (struct oboe_softc *)self;
187 	struct pci_attach_args *pa = aux;
188 	pci_intr_handle_t ih;
189 	struct ir_attach_args ia;
190 	const char *intrstring;
191 
192 	sc->sc_revision = PCI_REVISION(pa->pa_class);
193 	printf(": Toshiba Fast Infrared Type O, revision %d\n",
194 	       sc->sc_revision);
195 
196 	/* Map I/O registers. */
197 	if (pci_mapreg_map(pa, IO_BAR, PCI_MAPREG_TYPE_IO, 0,
198 	    &sc->sc_iot, &sc->sc_ioh, NULL, NULL)) {
199 		printf("%s: can't map I/O space\n", sc->sc_dev.dv_xname);
200 		return;
201 	}
202 
203 	sc->sc_dmatag = pa->pa_dmat;
204 
205 	ia.ia_type = IR_TYPE_IRFRAME;
206 	ia.ia_methods = &oboe_methods;
207 	ia.ia_handle = sc;
208 
209 	sc->sc_state = 0;
210 	sc->sc_speed = IRDA_SPEED_9600;
211 
212 	/* Enable the device */
213 	pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
214 	    pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) |
215 	    PCI_COMMAND_MASTER_ENABLE);
216 
217 	/* Reset the device; bail out upon failure. */
218 	if (oboe_reset(sc) != 0) {
219 		printf("%s: can't reset\n", sc->sc_dev.dv_xname);
220 		return;
221 	}
222 	/* Map and establish the interrupt. */
223 	if (pci_intr_map(pa, &ih)) {
224 		printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
225 		return;
226 	}
227 	intrstring = pci_intr_string(pa->pa_pc, ih);
228 	sc->sc_ih  = pci_intr_establish(pa->pa_pc, ih, IPL_IR, oboe_intr, sc);
229 	if (sc->sc_ih == NULL) {
230 		printf("%s: couldn't establish interrupt",
231 		    sc->sc_dev.dv_xname);
232 		if (intrstring != NULL)
233 			printf(" at %s", intrstring);
234 		printf("\n");
235 		return;
236 	}
237 	printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstring);
238 
239 	sc->sc_txs = 0;
240 	sc->sc_rxs = 0;
241 
242 	sc->sc_speeds =
243 		IRDA_SPEED_2400   | IRDA_SPEED_9600    | IRDA_SPEED_19200 |
244 		IRDA_SPEED_38400  | IRDA_SPEED_57600   | IRDA_SPEED_115200 |
245 		IRDA_SPEED_576000 | IRDA_SPEED_1152000 | IRDA_SPEED_4000000;
246 
247 	oboe_alloc_taskfile(sc);
248 
249 	sc->sc_child = config_found((void *)sc, &ia, ir_print);
250 }
251 
252 static int
253 oboe_activate(struct device *self, enum devact act)
254 {
255 	struct oboe_softc *sc = (struct oboe_softc *)self;
256 	int error = 0;
257 
258 	DPRINTF(("%s: sc=%p\n", __func__, sc));
259 
260 	switch (act) {
261 	case DVACT_ACTIVATE:
262 		return (EOPNOTSUPP);
263 		break;
264 
265 	case DVACT_DEACTIVATE:
266 		if (sc->sc_child != NULL)
267 			error = config_deactivate(sc->sc_child);
268 		break;
269 	}
270 	return (error);
271 }
272 
273 static int
274 oboe_detach(struct device *self, int flags)
275 {
276 #ifdef OBOE_DEBUG
277 	struct oboe_softc *sc = (struct oboe_softc *)self;
278 
279 	/* XXX needs reference counting for proper detach. */
280 	DPRINTF(("%s: sc=%p\n", __func__, sc));
281 #endif
282 	return (0);
283 }
284 
285 static int
286 oboe_open(void *h, int flag, int mode, struct lwp *l)
287 {
288 	struct oboe_softc *sc = h;
289 
290 	DPRINTF(("%s: sc=%p\n", __func__, sc));
291 
292 	sc->sc_state = 0;
293 	sc->sc_saved = 0;
294 	oboe_init_taskfile(sc);
295 	oboe_startchip(sc);
296 
297 	return (0);
298 }
299 
300 static int
301 oboe_close(void *h, int flag, int mode,
302     struct lwp *l)
303 {
304 	struct oboe_softc *sc = h;
305 	int error = 0;
306 	int s = splir();
307 
308 	DPRINTF(("%s: sc=%p\n", __func__, sc));
309 	/* Wait for output to drain */
310 
311 	if (sc->sc_txpending > 0) {
312 		sc->sc_state |= OBOE_CLOSING;
313 		error = tsleep(&sc->sc_state, PZERO | PCATCH, "oboecl", hz/10);
314 	}
315 	splx(s);
316 
317 	oboe_stopchip(sc);
318 	return (error);
319 }
320 
321 static int
322 oboe_read(void *h, struct uio *uio, int flag)
323 {
324 	struct oboe_softc *sc = h;
325 	int error = 0;
326 	int s;
327 	int slot;
328 
329 	DPRINTF(("%s: resid=%d, iovcnt=%d, offset=%ld\n",
330 		 __func__, uio->uio_resid, uio->uio_iovcnt,
331 		 (long)uio->uio_offset));
332 
333 	s = splir();
334 	while (sc->sc_saved == 0) {
335 		if (flag & IO_NDELAY) {
336 			splx(s);
337 			return (EWOULDBLOCK);
338 		}
339 		sc->sc_state |= OBOE_RSLP;
340 		DPRINTF(("oboe_read: sleep\n"));
341 		error = tsleep(&sc->sc_rxs, PZERO | PCATCH, "oboerd", 0);
342 		DPRINTF(("oboe_read: woke, error=%d\n", error));
343 		if (error) {
344 			sc->sc_state &= ~OBOE_RSLP;
345 			break;
346 		}
347 	}
348 
349 	/* Do just one frame transfer per read */
350 
351 	if (!error) {
352 		slot = (sc->sc_rxs - sc->sc_saved + RX_SLOTS) % RX_SLOTS;
353 		if (uio->uio_resid < sc->sc_lens[slot]) {
354 			DPRINTF(("oboe_read: uio buffer smaller than frame size"
355 			    "(%d < %d)\n", uio->uio_resid, sc->sc_lens[slot]));
356 			error = EINVAL;
357 		} else {
358 			DPRINTF(("oboe_read: moving %d bytes from %p\n",
359 				 sc->sc_lens[slot],
360 				 sc->sc_recv_stores[slot]));
361 			error = uiomove(sc->sc_recv_stores[slot],
362 					sc->sc_lens[slot], uio);
363 		}
364 	}
365 	sc->sc_saved--;
366 	splx(s);
367 
368 	return (error);
369 }
370 
371 static int
372 oboe_write(void *h, struct uio *uio, int flag)
373 {
374 	struct oboe_softc *sc = h;
375 	int error = 0;
376 	int n;
377 	int s = splir();
378 
379 	DPRINTF(("%s: sc=%p\n", __func__, sc));
380 	while (sc->sc_txpending == TX_SLOTS) {
381 		if (flag & IO_NDELAY) {
382 			splx(s);
383 			return (EWOULDBLOCK);
384 		}
385 		sc->sc_state |= OBOE_WSLP;
386 		DPRINTF(("oboe_write: sleep\n"));
387 		error = tsleep(&sc->sc_txs, PZERO | PCATCH, "oboewr", 0);
388 		DPRINTF(("oboe_write: woke up, error=%d\n", error));
389 		if (error) {
390 			sc->sc_state &= ~OBOE_WSLP;
391 			break;
392 		}
393 	}
394 	if (error)
395 		goto err;
396 	if (sc->sc_taskfile->xmit[sc->sc_txs].control) {
397 		DPRINTF(("oboe_write: slot overrun\n"));
398 	}
399 
400 	n = irda_sir_frame(sc->sc_xmit_bufs[sc->sc_txs], TX_BUF_SZ, uio,
401 			   sc->sc_ebofs);
402 	if (n < 0) {
403 		error = -n;
404 		goto err;
405 	}
406 	sc->sc_taskfile->xmit[sc->sc_txs].len = n;
407 
408 	OUTB(sc, 0, OBOE_RST);
409 	OUTB(sc, 0x1e, OBOE_REG_11);
410 
411 	sc->sc_taskfile->xmit[sc->sc_txs].control = 0x84;
412 
413 	/* XXX Need delay here??? */
414 	delay(1000);
415 
416 	sc->sc_txpending++;
417 	OUTB(sc, 0x80, OBOE_RST);
418 	OUTB(sc, 1, OBOE_REG_9);
419 	sc->sc_txs++;
420 	sc->sc_txs %= TX_SLOTS;
421 
422  err:
423 	splx(s);
424 	return (error);
425 }
426 
427 static int
428 oboe_set_params(void *h, struct irda_params *p)
429 {
430 	struct oboe_softc *sc = h;
431 	int error;
432 
433 	if (p->speed > 0) {
434 		error = oboe_setbaud(sc, p->speed);
435 		if (error)
436 			return (error);
437 	}
438 	sc->sc_ebofs = p->ebofs;
439 
440 	/* XXX ignore ebofs and maxsize for now */
441 	return (0);
442 }
443 
444 static int
445 oboe_get_speeds(void *h, int *speeds)
446 {
447 	struct oboe_softc *sc = h;
448 	*speeds = sc->sc_speeds;
449 	return (0);
450 }
451 
452 static int
453 oboe_get_turnarounds(void *h, int *turnarounds)
454 {
455 #ifdef OBOE_DEBUG
456 	struct oboe_softc *sc = h;
457 	DPRINTF(("%s: sc=%p\n", __func__, sc));
458 #endif
459 
460 	/* XXX Linux driver sets all bits */
461 	*turnarounds = IRDA_TURNT_10000; /* 10ms */
462 
463 	return (0);
464 }
465 
466 static int
467 oboe_poll(void *h, int events, struct lwp *l)
468 {
469 	struct oboe_softc *sc = h;
470 	int revents = 0;
471 	int s;
472 
473 	DPRINTF(("%s: sc=%p\n", __func__, sc));
474 
475 	s = splir();
476 	if (events & (POLLOUT | POLLWRNORM))
477 		revents |= events & (POLLOUT | POLLWRNORM);
478 	if (events & (POLLIN | POLLRDNORM)) {
479 		if (sc->sc_saved > 0) {
480 			DPRINTF(("%s: have data\n", __func__));
481 			revents |= events & (POLLIN | POLLRDNORM);
482 		} else {
483 			DPRINTF(("%s: recording select\n", __func__));
484 			selrecord(l, &sc->sc_rsel);
485 		}
486 	}
487 	splx(s);
488 
489 	return (revents);
490 }
491 
492 static void
493 filt_oboerdetach(struct knote *kn)
494 {
495 	struct oboe_softc *sc = kn->kn_hook;
496 	int s;
497 
498 	s = splir();
499 	SLIST_REMOVE(&sc->sc_rsel.sel_klist, kn, knote, kn_selnext);
500 	splx(s);
501 }
502 
503 static int
504 filt_oboeread(struct knote *kn, long hint)
505 {
506 	struct oboe_softc *sc = kn->kn_hook;
507 
508 	kn->kn_data = sc->sc_saved;
509 	return (kn->kn_data > 0);
510 }
511 
512 static void
513 filt_oboewdetach(struct knote *kn)
514 {
515 	struct oboe_softc *sc = kn->kn_hook;
516 	int s;
517 
518 	s = splir();
519 	SLIST_REMOVE(&sc->sc_wsel.sel_klist, kn, knote, kn_selnext);
520 	splx(s);
521 }
522 
523 static const struct filterops oboeread_filtops =
524 	{ 1, NULL, filt_oboerdetach, filt_oboeread };
525 static const struct filterops oboewrite_filtops =
526 	{ 1, NULL, filt_oboewdetach, filt_seltrue };
527 
528 static int
529 oboe_kqfilter(void *h, struct knote *kn)
530 {
531 	struct oboe_softc *sc = h;
532 	struct klist *klist;
533 	int s;
534 
535 	switch (kn->kn_filter) {
536 	case EVFILT_READ:
537 		klist = &sc->sc_rsel.sel_klist;
538 		kn->kn_fop = &oboeread_filtops;
539 		break;
540 	case EVFILT_WRITE:
541 		klist = &sc->sc_wsel.sel_klist;
542 		kn->kn_fop = &oboewrite_filtops;
543 		break;
544 	default:
545 		return (EINVAL);
546 	}
547 
548 	kn->kn_hook = sc;
549 
550 	s = splir();
551 	SLIST_INSERT_HEAD(klist, kn, kn_selnext);
552 	splx(s);
553 
554 	return (0);
555 }
556 
557 static int
558 oboe_reset(struct oboe_softc *sc)
559 {
560 #if 0
561 	OUTB(sc, 0x00, OBOE_RST);
562 	OUTB(sc, 0x80, OBOE_RST);
563 #endif
564 	return 0;
565 }
566 
567 static int
568 oboe_intr(void *p)
569 {
570 	struct oboe_softc *sc = p;
571 	uint8_t irqstat	= INB(sc, OBOE_ISR);
572 
573 	if (!(irqstat & 0xf8))
574 		return (0); /* Not for me? */
575 
576 	DPRINTF(("oboe_intr stat=0x%x\n", irqstat));
577 
578 	OUTB(sc, irqstat, OBOE_ISR);
579 
580 	if (irqstat & OBOE_ISR_RXDONE) {
581 		while (sc->sc_taskfile->recv[sc->sc_rxs].control == 0) {
582 			int len = sc->sc_taskfile->recv[sc->sc_rxs].len;
583 			if (sc->sc_saved == RX_SLOTS) {
584 				DPRINTF(("oboe_intr: all buffers filled\n"));
585 				return 0;
586 			}
587 
588 			if (len > 2)
589 				len -= 2; /* JSP: skip check sum? */
590 
591 			DPRINTF(("oboe_intr: moving %d bytes to %p\n", len,
592 				 sc->sc_recv_stores[sc->sc_rxs]));
593 			memcpy(sc->sc_recv_stores[sc->sc_rxs],
594 			       sc->sc_recv_bufs[sc->sc_rxs],
595 			       len);
596 			sc->sc_lens[sc->sc_rxs] = len;
597 			sc->sc_saved++;
598 #if 0
599 			(void)b_to_q(sc->sc_recv_bufs[sc->sc_rxs],
600 				     len, &sc->sc_q);
601 #endif
602 			sc->sc_taskfile->recv[sc->sc_rxs].control = 0x83;
603 			sc->sc_taskfile->recv[sc->sc_rxs].len = 0x0;
604 			sc->sc_rxs = (sc->sc_rxs + 1) % RX_SLOTS;
605 			DPRINTF(("oboe_intr new rxs=%d\n", sc->sc_rxs));
606 		}
607 		DPRINTF(("oboe_intr no more frames available\n"));
608 		if (sc->sc_state & OBOE_RSLP) {
609 			DPRINTF(("oboe_intr changing state to ~OBOE_RSLP\n"));
610 			sc->sc_state &= ~OBOE_RSLP;
611 			DPRINTF(("oboe_intr: waking up reader\n"));
612 			wakeup(&sc->sc_rxs);
613 		}
614 		selnotify(&sc->sc_rsel, 0);
615 		DPRINTF(("oboe_intr returning\n"));
616 	}
617 	if (irqstat & OBOE_ISR_TXDONE) {
618 	        DPRINTF(("oboe_intr: write done\n"));
619 		sc->sc_txpending--;
620 		sc->sc_txpackets++;
621 
622 		if ((sc->sc_state & OBOE_CLOSING) && sc->sc_txpending == 0) {
623 			wakeup(&sc->sc_state);
624 			return 1;
625 		}
626 
627 		if (sc->sc_state & OBOE_WSLP) {
628 			DPRINTF(("oboe_intr changing state to ~OBOE_WSLP\n"));
629 			sc->sc_state &= ~OBOE_WSLP;
630 			DPRINTF(("oboe_intr: waking up writer\n"));
631 			wakeup(&sc->sc_txs);
632 		}
633 		selnotify(&sc->sc_wsel, 0);
634 	}
635 	return (1);
636 }
637 
638 /* XXX vtophys must go! */
639 static void
640 oboe_init_taskfile(struct oboe_softc *sc)
641 {
642 	int i;
643 	int s = splir();
644 
645 	for (i = 0; i < TX_SLOTS; ++i) {
646 		sc->sc_taskfile->xmit[i].len = 0;
647 		sc->sc_taskfile->xmit[i].control = 0x00;
648 		sc->sc_taskfile->xmit[i].buffer =
649 			vtophys((u_int)sc->sc_xmit_bufs[i]); /* u_int? */
650 	}
651 
652 	for (i = 0; i < RX_SLOTS; ++i) {
653 		sc->sc_taskfile->recv[i].len = 0;
654 		sc->sc_taskfile->recv[i].control = 0x83;
655 		sc->sc_taskfile->recv[i].buffer =
656 			vtophys((u_int)sc->sc_recv_bufs[i]); /* u_int? */
657 	}
658 
659 	sc->sc_txpending = 0;
660 
661 	splx(s);
662 }
663 
664 static int
665 oboe_alloc_taskfile(struct oboe_softc *sc)
666 {
667 	int i;
668 	/* XXX */
669 	uint32_t addr = (uint32_t)malloc(OBOE_TASK_BUF_LEN, M_DEVBUF, M_WAITOK);
670 	if (addr == 0) {
671 		goto bad;
672 	}
673 	addr &= ~(sizeof (struct OboeTaskFile) - 1);
674 	addr += sizeof (struct OboeTaskFile);
675 	sc->sc_taskfile = (struct OboeTaskFile *) addr;
676 
677 	for (i = 0; i < TX_SLOTS; ++i) {
678 		sc->sc_xmit_bufs[i] =
679 			malloc(TX_BUF_SZ, M_DEVBUF, M_WAITOK);
680 		sc->sc_xmit_stores[i] =
681 			malloc(TX_BUF_SZ, M_DEVBUF, M_WAITOK);
682 		if (sc->sc_xmit_bufs[i] == NULL ||
683 		    sc->sc_xmit_stores[i] == NULL) {
684 			goto bad;
685 		}
686 	}
687 	for (i = 0; i < RX_SLOTS; ++i) {
688 		sc->sc_recv_bufs[i] =
689 			malloc(RX_BUF_SZ, M_DEVBUF, M_WAITOK);
690 		sc->sc_recv_stores[i] =
691 			malloc(RX_BUF_SZ, M_DEVBUF, M_WAITOK);
692 		if (sc->sc_recv_bufs[i] == NULL ||
693 		    sc->sc_recv_stores[i] == NULL) {
694 			goto bad;
695 		}
696 	}
697 
698 	return 0;
699 bad:
700 	printf("oboe: malloc for buffers failed()\n");
701 	return 1;
702 }
703 
704 static void
705 oboe_startchip (struct oboe_softc *sc)
706 {
707 	uint32_t physaddr;
708 
709 	OUTB(sc, 0, OBOE_LOCK);
710 	OUTB(sc, 0, OBOE_RST);
711 	OUTB(sc, OBOE_NTR_VAL, OBOE_NTR);
712 	OUTB(sc, 0xf0, OBOE_REG_D);
713 	OUTB(sc, 0xff, OBOE_ISR);
714 	OUTB(sc, 0x0f, OBOE_REG_1A);
715 	OUTB(sc, 0xff, OBOE_REG_1B);
716 
717 	physaddr = vtophys((u_int)sc->sc_taskfile); /* u_int? */
718 
719 	OUTB(sc, (physaddr >> 0x0a) & 0xff, OBOE_TFP0);
720 	OUTB(sc, (physaddr >> 0x12) & 0xff, OBOE_TFP1);
721 	OUTB(sc, (physaddr >> 0x1a) & 0x3f, OBOE_TFP2);
722 
723 	OUTB(sc, 0x0e, OBOE_REG_11);
724 	OUTB(sc, 0x80, OBOE_RST);
725 
726 	(void)oboe_setbaud(sc, 9600);
727 
728 	sc->sc_rxs = INB(sc, OBOE_RCVT);
729 	if (sc->sc_rxs < 0 || sc->sc_rxs >= RX_SLOTS)
730 		sc->sc_rxs = 0;
731 	sc->sc_txs = INB(sc, OBOE_XMTT) - OBOE_XMTT_OFFSET;
732 	if (sc->sc_txs < 0 || sc->sc_txs >= TX_SLOTS)
733 		sc->sc_txs = 0;
734 }
735 
736 static void
737 oboe_stopchip (struct oboe_softc *sc)
738 {
739 	OUTB(sc, 0x0e, OBOE_REG_11);
740 	OUTB(sc, 0x00, OBOE_RST);
741 	OUTB(sc, 0x3f, OBOE_TFP2);     /* Write the taskfile address */
742 	OUTB(sc, 0xff, OBOE_TFP1);
743 	OUTB(sc, 0xff, OBOE_TFP0);
744 	OUTB(sc, 0x0f, OBOE_REG_1B);
745 	OUTB(sc, 0xff, OBOE_REG_1A);
746 	OUTB(sc, 0x00, OBOE_ISR); /* XXX: should i do this to disable ints? */
747 	OUTB(sc, 0x80, OBOE_RST);
748 	OUTB(sc, 0x0e, OBOE_LOCK);
749 }
750 
751 #define SPEEDCASE(speed, type, divisor) \
752 case speed: \
753 OUTB(sc, OBOE_PMDL_##type, OBOE_PMDL); \
754 OUTB(sc, OBOE_SMDL_##type, OBOE_SMDL); \
755 OUTB(sc, divisor, OBOE_UDIV); \
756 break
757 
758 static int
759 oboe_setbaud(struct oboe_softc *sc, int baud)
760 {
761 	int s;
762 
763 	DPRINTF(("oboe: setting baud to %d\n", baud));
764 
765 	s = splir();
766 
767 	switch (baud) {
768 	SPEEDCASE(   2400, SIR, 0xbf);
769 	SPEEDCASE(   9600, SIR, 0x2f);
770 	SPEEDCASE(  19200, SIR, 0x17);
771 	SPEEDCASE(  38400, SIR, 0x0b);
772 	SPEEDCASE(  57600, SIR, 0x07);
773 	SPEEDCASE( 115200, SIR, 0x03);
774 	SPEEDCASE(1152000, MIR, 0x01);
775 	SPEEDCASE(4000000, FIR, 0x00);
776 	default:
777 		DPRINTF(("oboe: cannot set speed to %d\n", baud));
778 		splx(s);
779 		return (EINVAL);
780 	}
781 
782 	OUTB(sc, 0x00, OBOE_RST);
783 	OUTB(sc, 0x80, OBOE_RST);
784 	OUTB(sc, 0x01, OBOE_REG_9);
785 
786 	sc->sc_speed = baud;
787 
788 	splx(s);
789 
790 	return (0);
791 }
792