1 /* $NetBSD: oboe.c,v 1.36 2009/11/12 19:41:05 dyoung Exp $ */
3 /* XXXXFVDL THIS DRIVER IS BROKEN FOR NON-i386 -- vtophys() usage */
6 * Copyright (c) 2001 The NetBSD Foundation, Inc.
9 * This code is derived from software contributed to The NetBSD Foundation
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
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.
21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
35 * Toshiba OBOE IrDA SIR/FIR driver.
37 * Based on information from the Linux driver, thus the magic hex numbers.
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: oboe.c,v 1.36 2009/11/12 19:41:05 dyoung Exp $");
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/kernel.h>
46 #include <sys/device.h>
47 #include <sys/malloc.h>
49 #include <sys/vnode.h>
53 #include <dev/ir/ir.h>
54 #include <dev/ir/irdaio.h>
55 #include <dev/ir/irframevar.h>
56 #include <dev/ir/sir.h>
58 #include <dev/pci/pcidevs.h>
59 #include <dev/pci/pcivar.h>
63 #include <uvm/uvm_extern.h>
65 #include <dev/pci/oboereg.h>
67 static int oboe_match(device_t parent
, cfdata_t match
, void *aux
);
68 static void oboe_attach(device_t parent
, device_t self
, void *aux
);
69 static int oboe_detach(device_t self
, int flags
);
71 static int oboe_open(void *h
, int flag
, int mode
, struct lwp
*l
);
72 static int oboe_close(void *h
, int flag
, int mode
, struct lwp
*l
);
73 static int oboe_read(void *h
, struct uio
*uio
, int flag
);
74 static int oboe_write(void *h
, struct uio
*uio
, int flag
);
75 static int oboe_set_params(void *h
, struct irda_params
*params
);
76 static int oboe_get_speeds(void *h
, int *speeds
);
77 static int oboe_get_turnarounds(void *h
, int *times
);
78 static int oboe_poll(void *h
, int events
, struct lwp
*l
);
79 static int oboe_kqfilter(void *h
, struct knote
*kn
);
82 #define DPRINTF(x) if (oboedebug) printf x
92 struct device
*sc_child
;
93 struct pci_attach_args sc_pa
;
94 pci_intr_handle_t
* sc_ih
;
95 unsigned int sc_revision
; /* PCI Revision ID */
97 bus_space_tag_t sc_iot
;
98 bus_space_handle_t sc_ioh
;
99 bus_dma_tag_t sc_dmatag
;
100 struct selinfo sc_rsel
;
101 struct selinfo sc_wsel
;
104 #define OBOE_RSLP 0x01 /* waiting for data (read) */
105 #define OBOE_WSLP 0x02 /* waiting for data (write) */
106 #define OBOE_CLOSING 0x04 /* waiting for output to drain */
113 struct oboe_dma
*sc_dmas
;
114 struct OboeTaskFile
*sc_taskfile
; /* The taskfile */
115 u_char
* sc_xmit_bufs
[TX_SLOTS
];
116 u_char
* sc_recv_bufs
[RX_SLOTS
];
117 void * sc_xmit_stores
[TX_SLOTS
];
118 void * sc_recv_stores
[RX_SLOTS
];
119 int sc_txs
; /* Current transmit slot number */
120 int sc_rxs
; /* Current receive slot number */
121 int sc_saved
; /* number of saved frames */
122 int sc_lens
[RX_SLOTS
];
133 static int oboe_intr(void *handle
);
134 static int oboe_reset(struct oboe_softc
*);
139 bus_dma_segment_t segs
[1];
142 struct oboe_dma
*next
;
145 #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr)
146 #define KERNADDR(p) ((void *)((p)->addr))
148 static int oboe_alloc_taskfile(struct oboe_softc
*);
149 static void oboe_init_taskfile(struct oboe_softc
*);
150 static void oboe_startchip(struct oboe_softc
*);
151 static void oboe_stopchip(struct oboe_softc
*);
152 static int oboe_setbaud(struct oboe_softc
*, int);
154 CFATTACH_DECL(oboe
, sizeof(struct oboe_softc
),
155 oboe_match
, oboe_attach
, oboe_detach
, NULL
);
157 static struct irframe_methods oboe_methods
= {
158 oboe_open
, oboe_close
, oboe_read
, oboe_write
, oboe_poll
,
159 oboe_kqfilter
, oboe_set_params
, oboe_get_speeds
, oboe_get_turnarounds
163 oboe_match(device_t parent
, cfdata_t match
, void *aux
)
165 struct pci_attach_args
*pa
= aux
;
167 if (PCI_VENDOR(pa
->pa_id
) == PCI_VENDOR_TOSHIBA2
&&
168 (PCI_PRODUCT(pa
->pa_id
) == PCI_PRODUCT_TOSHIBA2_OBOE
||
169 PCI_PRODUCT(pa
->pa_id
) == PCI_PRODUCT_TOSHIBA2_DONAUOBOE
))
175 oboe_attach(device_t parent
, device_t self
, void *aux
)
177 struct oboe_softc
*sc
= device_private(self
);
178 struct pci_attach_args
*pa
= aux
;
179 pci_intr_handle_t ih
;
180 struct ir_attach_args ia
;
181 const char *intrstring
;
183 sc
->sc_revision
= PCI_REVISION(pa
->pa_class
);
184 printf(": Toshiba Fast Infrared Type O, revision %d\n",
187 /* Map I/O registers. */
188 if (pci_mapreg_map(pa
, IO_BAR
, PCI_MAPREG_TYPE_IO
, 0,
189 &sc
->sc_iot
, &sc
->sc_ioh
, NULL
, NULL
)) {
190 aprint_error_dev(&sc
->sc_dev
, "can't map I/O space\n");
194 sc
->sc_dmatag
= pa
->pa_dmat
;
196 ia
.ia_type
= IR_TYPE_IRFRAME
;
197 ia
.ia_methods
= &oboe_methods
;
201 sc
->sc_speed
= IRDA_SPEED_9600
;
203 /* Enable the device */
204 pci_conf_write(pa
->pa_pc
, pa
->pa_tag
, PCI_COMMAND_STATUS_REG
,
205 pci_conf_read(pa
->pa_pc
, pa
->pa_tag
, PCI_COMMAND_STATUS_REG
) |
206 PCI_COMMAND_MASTER_ENABLE
);
208 /* Reset the device; bail out upon failure. */
209 if (oboe_reset(sc
) != 0) {
210 aprint_error_dev(&sc
->sc_dev
, "can't reset\n");
213 /* Map and establish the interrupt. */
214 if (pci_intr_map(pa
, &ih
)) {
215 aprint_error_dev(&sc
->sc_dev
, "couldn't map interrupt\n");
218 intrstring
= pci_intr_string(pa
->pa_pc
, ih
);
219 sc
->sc_ih
= pci_intr_establish(pa
->pa_pc
, ih
, IPL_IR
, oboe_intr
, sc
);
220 if (sc
->sc_ih
== NULL
) {
221 aprint_error_dev(&sc
->sc_dev
, "couldn't establish interrupt");
222 if (intrstring
!= NULL
)
223 aprint_error(" at %s", intrstring
);
227 aprint_normal_dev(&sc
->sc_dev
, "interrupting at %s\n", intrstring
);
229 selinit(&sc
->sc_rsel
);
230 selinit(&sc
->sc_wsel
);
236 IRDA_SPEED_2400
| IRDA_SPEED_9600
| IRDA_SPEED_19200
|
237 IRDA_SPEED_38400
| IRDA_SPEED_57600
| IRDA_SPEED_115200
|
238 IRDA_SPEED_576000
| IRDA_SPEED_1152000
| IRDA_SPEED_4000000
;
240 oboe_alloc_taskfile(sc
);
242 sc
->sc_child
= config_found((void *)sc
, &ia
, ir_print
);
246 oboe_detach(device_t self
, int flags
)
248 struct oboe_softc
*sc
= device_private(self
);
251 /* XXX needs reference counting for proper detach. */
252 DPRINTF(("%s: sc=%p\n", __func__
, sc
));
254 seldestroy(&sc
->sc_rsel
);
255 seldestroy(&sc
->sc_wsel
);
260 oboe_open(void *h
, int flag
, int mode
, struct lwp
*l
)
262 struct oboe_softc
*sc
= h
;
264 DPRINTF(("%s: sc=%p\n", __func__
, sc
));
268 oboe_init_taskfile(sc
);
275 oboe_close(void *h
, int flag
, int mode
,
278 struct oboe_softc
*sc
= h
;
282 DPRINTF(("%s: sc=%p\n", __func__
, sc
));
283 /* Wait for output to drain */
285 if (sc
->sc_txpending
> 0) {
286 sc
->sc_state
|= OBOE_CLOSING
;
287 error
= tsleep(&sc
->sc_state
, PZERO
| PCATCH
, "oboecl", hz
/10);
296 oboe_read(void *h
, struct uio
*uio
, int flag
)
298 struct oboe_softc
*sc
= h
;
303 DPRINTF(("%s: resid=%d, iovcnt=%d, offset=%ld\n",
304 __func__
, uio
->uio_resid
, uio
->uio_iovcnt
,
305 (long)uio
->uio_offset
));
308 while (sc
->sc_saved
== 0) {
309 if (flag
& IO_NDELAY
) {
311 return (EWOULDBLOCK
);
313 sc
->sc_state
|= OBOE_RSLP
;
314 DPRINTF(("oboe_read: sleep\n"));
315 error
= tsleep(&sc
->sc_rxs
, PZERO
| PCATCH
, "oboerd", 0);
316 DPRINTF(("oboe_read: woke, error=%d\n", error
));
318 sc
->sc_state
&= ~OBOE_RSLP
;
323 /* Do just one frame transfer per read */
326 slot
= (sc
->sc_rxs
- sc
->sc_saved
+ RX_SLOTS
) % RX_SLOTS
;
327 if (uio
->uio_resid
< sc
->sc_lens
[slot
]) {
328 DPRINTF(("oboe_read: uio buffer smaller than frame size"
329 "(%d < %d)\n", uio
->uio_resid
, sc
->sc_lens
[slot
]));
332 DPRINTF(("oboe_read: moving %d bytes from %p\n",
334 sc
->sc_recv_stores
[slot
]));
335 error
= uiomove(sc
->sc_recv_stores
[slot
],
336 sc
->sc_lens
[slot
], uio
);
346 oboe_write(void *h
, struct uio
*uio
, int flag
)
348 struct oboe_softc
*sc
= h
;
353 DPRINTF(("%s: sc=%p\n", __func__
, sc
));
354 while (sc
->sc_txpending
== TX_SLOTS
) {
355 if (flag
& IO_NDELAY
) {
357 return (EWOULDBLOCK
);
359 sc
->sc_state
|= OBOE_WSLP
;
360 DPRINTF(("oboe_write: sleep\n"));
361 error
= tsleep(&sc
->sc_txs
, PZERO
| PCATCH
, "oboewr", 0);
362 DPRINTF(("oboe_write: woke up, error=%d\n", error
));
364 sc
->sc_state
&= ~OBOE_WSLP
;
370 if (sc
->sc_taskfile
->xmit
[sc
->sc_txs
].control
) {
371 DPRINTF(("oboe_write: slot overrun\n"));
374 n
= irda_sir_frame(sc
->sc_xmit_bufs
[sc
->sc_txs
], TX_BUF_SZ
, uio
,
380 sc
->sc_taskfile
->xmit
[sc
->sc_txs
].len
= n
;
382 OUTB(sc
, 0, OBOE_RST
);
383 OUTB(sc
, 0x1e, OBOE_REG_11
);
385 sc
->sc_taskfile
->xmit
[sc
->sc_txs
].control
= 0x84;
387 /* XXX Need delay here??? */
391 OUTB(sc
, 0x80, OBOE_RST
);
392 OUTB(sc
, 1, OBOE_REG_9
);
394 sc
->sc_txs
%= TX_SLOTS
;
402 oboe_set_params(void *h
, struct irda_params
*p
)
404 struct oboe_softc
*sc
= h
;
408 error
= oboe_setbaud(sc
, p
->speed
);
412 sc
->sc_ebofs
= p
->ebofs
;
414 /* XXX ignore ebofs and maxsize for now */
419 oboe_get_speeds(void *h
, int *speeds
)
421 struct oboe_softc
*sc
= h
;
422 *speeds
= sc
->sc_speeds
;
427 oboe_get_turnarounds(void *h
, int *turnarounds
)
430 struct oboe_softc
*sc
= h
;
431 DPRINTF(("%s: sc=%p\n", __func__
, sc
));
434 /* XXX Linux driver sets all bits */
435 *turnarounds
= IRDA_TURNT_10000
; /* 10ms */
441 oboe_poll(void *h
, int events
, struct lwp
*l
)
443 struct oboe_softc
*sc
= h
;
447 DPRINTF(("%s: sc=%p\n", __func__
, sc
));
450 if (events
& (POLLOUT
| POLLWRNORM
))
451 revents
|= events
& (POLLOUT
| POLLWRNORM
);
452 if (events
& (POLLIN
| POLLRDNORM
)) {
453 if (sc
->sc_saved
> 0) {
454 DPRINTF(("%s: have data\n", __func__
));
455 revents
|= events
& (POLLIN
| POLLRDNORM
);
457 DPRINTF(("%s: recording select\n", __func__
));
458 selrecord(l
, &sc
->sc_rsel
);
467 filt_oboerdetach(struct knote
*kn
)
469 struct oboe_softc
*sc
= kn
->kn_hook
;
473 SLIST_REMOVE(&sc
->sc_rsel
.sel_klist
, kn
, knote
, kn_selnext
);
478 filt_oboeread(struct knote
*kn
, long hint
)
480 struct oboe_softc
*sc
= kn
->kn_hook
;
482 kn
->kn_data
= sc
->sc_saved
;
483 return (kn
->kn_data
> 0);
487 filt_oboewdetach(struct knote
*kn
)
489 struct oboe_softc
*sc
= kn
->kn_hook
;
493 SLIST_REMOVE(&sc
->sc_wsel
.sel_klist
, kn
, knote
, kn_selnext
);
497 static const struct filterops oboeread_filtops
=
498 { 1, NULL
, filt_oboerdetach
, filt_oboeread
};
499 static const struct filterops oboewrite_filtops
=
500 { 1, NULL
, filt_oboewdetach
, filt_seltrue
};
503 oboe_kqfilter(void *h
, struct knote
*kn
)
505 struct oboe_softc
*sc
= h
;
509 switch (kn
->kn_filter
) {
511 klist
= &sc
->sc_rsel
.sel_klist
;
512 kn
->kn_fop
= &oboeread_filtops
;
515 klist
= &sc
->sc_wsel
.sel_klist
;
516 kn
->kn_fop
= &oboewrite_filtops
;
525 SLIST_INSERT_HEAD(klist
, kn
, kn_selnext
);
532 oboe_reset(struct oboe_softc
*sc
)
535 OUTB(sc
, 0x00, OBOE_RST
);
536 OUTB(sc
, 0x80, OBOE_RST
);
544 struct oboe_softc
*sc
= p
;
545 uint8_t irqstat
= INB(sc
, OBOE_ISR
);
547 if (!(irqstat
& 0xf8))
548 return (0); /* Not for me? */
550 DPRINTF(("oboe_intr stat=0x%x\n", irqstat
));
552 OUTB(sc
, irqstat
, OBOE_ISR
);
554 if (irqstat
& OBOE_ISR_RXDONE
) {
555 while (sc
->sc_taskfile
->recv
[sc
->sc_rxs
].control
== 0) {
556 int len
= sc
->sc_taskfile
->recv
[sc
->sc_rxs
].len
;
557 if (sc
->sc_saved
== RX_SLOTS
) {
558 DPRINTF(("oboe_intr: all buffers filled\n"));
563 len
-= 2; /* JSP: skip check sum? */
565 DPRINTF(("oboe_intr: moving %d bytes to %p\n", len
,
566 sc
->sc_recv_stores
[sc
->sc_rxs
]));
567 memcpy(sc
->sc_recv_stores
[sc
->sc_rxs
],
568 sc
->sc_recv_bufs
[sc
->sc_rxs
],
570 sc
->sc_lens
[sc
->sc_rxs
] = len
;
573 (void)b_to_q(sc
->sc_recv_bufs
[sc
->sc_rxs
],
576 sc
->sc_taskfile
->recv
[sc
->sc_rxs
].control
= 0x83;
577 sc
->sc_taskfile
->recv
[sc
->sc_rxs
].len
= 0x0;
578 sc
->sc_rxs
= (sc
->sc_rxs
+ 1) % RX_SLOTS
;
579 DPRINTF(("oboe_intr new rxs=%d\n", sc
->sc_rxs
));
581 DPRINTF(("oboe_intr no more frames available\n"));
582 if (sc
->sc_state
& OBOE_RSLP
) {
583 DPRINTF(("oboe_intr changing state to ~OBOE_RSLP\n"));
584 sc
->sc_state
&= ~OBOE_RSLP
;
585 DPRINTF(("oboe_intr: waking up reader\n"));
588 selnotify(&sc
->sc_rsel
, 0, 0);
589 DPRINTF(("oboe_intr returning\n"));
591 if (irqstat
& OBOE_ISR_TXDONE
) {
592 DPRINTF(("oboe_intr: write done\n"));
596 if ((sc
->sc_state
& OBOE_CLOSING
) && sc
->sc_txpending
== 0) {
597 wakeup(&sc
->sc_state
);
601 if (sc
->sc_state
& OBOE_WSLP
) {
602 DPRINTF(("oboe_intr changing state to ~OBOE_WSLP\n"));
603 sc
->sc_state
&= ~OBOE_WSLP
;
604 DPRINTF(("oboe_intr: waking up writer\n"));
607 selnotify(&sc
->sc_wsel
, 0, 0);
612 /* XXX vtophys must go! */
614 oboe_init_taskfile(struct oboe_softc
*sc
)
619 for (i
= 0; i
< TX_SLOTS
; ++i
) {
620 sc
->sc_taskfile
->xmit
[i
].len
= 0;
621 sc
->sc_taskfile
->xmit
[i
].control
= 0x00;
622 sc
->sc_taskfile
->xmit
[i
].buffer
=
623 vtophys((u_int
)sc
->sc_xmit_bufs
[i
]); /* u_int? */
626 for (i
= 0; i
< RX_SLOTS
; ++i
) {
627 sc
->sc_taskfile
->recv
[i
].len
= 0;
628 sc
->sc_taskfile
->recv
[i
].control
= 0x83;
629 sc
->sc_taskfile
->recv
[i
].buffer
=
630 vtophys((u_int
)sc
->sc_recv_bufs
[i
]); /* u_int? */
633 sc
->sc_txpending
= 0;
639 oboe_alloc_taskfile(struct oboe_softc
*sc
)
643 uint32_t addr
= (uint32_t)malloc(OBOE_TASK_BUF_LEN
, M_DEVBUF
, M_WAITOK
);
647 addr
&= ~(sizeof (struct OboeTaskFile
) - 1);
648 addr
+= sizeof (struct OboeTaskFile
);
649 sc
->sc_taskfile
= (struct OboeTaskFile
*) addr
;
651 for (i
= 0; i
< TX_SLOTS
; ++i
) {
652 sc
->sc_xmit_bufs
[i
] =
653 malloc(TX_BUF_SZ
, M_DEVBUF
, M_WAITOK
);
654 sc
->sc_xmit_stores
[i
] =
655 malloc(TX_BUF_SZ
, M_DEVBUF
, M_WAITOK
);
656 if (sc
->sc_xmit_bufs
[i
] == NULL
||
657 sc
->sc_xmit_stores
[i
] == NULL
) {
661 for (i
= 0; i
< RX_SLOTS
; ++i
) {
662 sc
->sc_recv_bufs
[i
] =
663 malloc(RX_BUF_SZ
, M_DEVBUF
, M_WAITOK
);
664 sc
->sc_recv_stores
[i
] =
665 malloc(RX_BUF_SZ
, M_DEVBUF
, M_WAITOK
);
666 if (sc
->sc_recv_bufs
[i
] == NULL
||
667 sc
->sc_recv_stores
[i
] == NULL
) {
674 printf("oboe: malloc for buffers failed()\n");
679 oboe_startchip (struct oboe_softc
*sc
)
683 OUTB(sc
, 0, OBOE_LOCK
);
684 OUTB(sc
, 0, OBOE_RST
);
685 OUTB(sc
, OBOE_NTR_VAL
, OBOE_NTR
);
686 OUTB(sc
, 0xf0, OBOE_REG_D
);
687 OUTB(sc
, 0xff, OBOE_ISR
);
688 OUTB(sc
, 0x0f, OBOE_REG_1A
);
689 OUTB(sc
, 0xff, OBOE_REG_1B
);
691 physaddr
= vtophys((u_int
)sc
->sc_taskfile
); /* u_int? */
693 OUTB(sc
, (physaddr
>> 0x0a) & 0xff, OBOE_TFP0
);
694 OUTB(sc
, (physaddr
>> 0x12) & 0xff, OBOE_TFP1
);
695 OUTB(sc
, (physaddr
>> 0x1a) & 0x3f, OBOE_TFP2
);
697 OUTB(sc
, 0x0e, OBOE_REG_11
);
698 OUTB(sc
, 0x80, OBOE_RST
);
700 (void)oboe_setbaud(sc
, 9600);
702 sc
->sc_rxs
= INB(sc
, OBOE_RCVT
);
703 if (sc
->sc_rxs
< 0 || sc
->sc_rxs
>= RX_SLOTS
)
705 sc
->sc_txs
= INB(sc
, OBOE_XMTT
) - OBOE_XMTT_OFFSET
;
706 if (sc
->sc_txs
< 0 || sc
->sc_txs
>= TX_SLOTS
)
711 oboe_stopchip (struct oboe_softc
*sc
)
713 OUTB(sc
, 0x0e, OBOE_REG_11
);
714 OUTB(sc
, 0x00, OBOE_RST
);
715 OUTB(sc
, 0x3f, OBOE_TFP2
); /* Write the taskfile address */
716 OUTB(sc
, 0xff, OBOE_TFP1
);
717 OUTB(sc
, 0xff, OBOE_TFP0
);
718 OUTB(sc
, 0x0f, OBOE_REG_1B
);
719 OUTB(sc
, 0xff, OBOE_REG_1A
);
720 OUTB(sc
, 0x00, OBOE_ISR
); /* XXX: should i do this to disable ints? */
721 OUTB(sc
, 0x80, OBOE_RST
);
722 OUTB(sc
, 0x0e, OBOE_LOCK
);
725 #define SPEEDCASE(speed, type, divisor) \
727 OUTB(sc, OBOE_PMDL_##type, OBOE_PMDL); \
728 OUTB(sc, OBOE_SMDL_##type, OBOE_SMDL); \
729 OUTB(sc, divisor, OBOE_UDIV); \
733 oboe_setbaud(struct oboe_softc
*sc
, int baud
)
737 DPRINTF(("oboe: setting baud to %d\n", baud
));
742 SPEEDCASE( 2400, SIR
, 0xbf);
743 SPEEDCASE( 9600, SIR
, 0x2f);
744 SPEEDCASE( 19200, SIR
, 0x17);
745 SPEEDCASE( 38400, SIR
, 0x0b);
746 SPEEDCASE( 57600, SIR
, 0x07);
747 SPEEDCASE( 115200, SIR
, 0x03);
748 SPEEDCASE(1152000, MIR
, 0x01);
749 SPEEDCASE(4000000, FIR
, 0x00);
751 DPRINTF(("oboe: cannot set speed to %d\n", baud
));
756 OUTB(sc
, 0x00, OBOE_RST
);
757 OUTB(sc
, 0x80, OBOE_RST
);
758 OUTB(sc
, 0x01, OBOE_REG_9
);