1 /* $NetBSD: addcom_isa.c,v 1.18 2009/05/12 08:44:19 cegger Exp $ */
4 * Copyright (c) 2000 Michael Graff. All rights reserved.
5 * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
6 * Copyright (c) 1995 Charles M. Hannum. All rights reserved.
8 * This code is derived from public-domain software written by
9 * Roland McGrath, and information provided by David Muir Sharnoff.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by Charles M. Hannum.
22 * 4. The name of the author may not be used to endorse or promote products
23 * derived from this software without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 * This code was written and tested with the Addonics FlexPort 8S.
39 * It has 8 ports, using 16650-compatible chips, sharing a single
42 * An interrupt status register exists at 0x240, according to the
43 * skimpy documentation supplied. It doesn't change depending on
44 * io base address, so only one of these cards can ever be used at
47 * This card is different from the boca or other cards in that ports
48 * 0..5 are from addresses 0x108..0x137, and 6..7 are from 0x200..0x20f,
49 * making a gap that the other cards do not have.
51 * The addresses which are documented are 0x108, 0x1108, 0x1d08, and
52 * 0x8508, for the base (port 0) address.
54 * --Michael <explorer@NetBSD.org> -- April 21, 2000
57 #include <sys/cdefs.h>
58 __KERNEL_RCSID(0, "$NetBSD: addcom_isa.c,v 1.18 2009/05/12 08:44:19 cegger Exp $");
60 #include <sys/param.h>
61 #include <sys/systm.h>
62 #include <sys/device.h>
63 #include <sys/termios.h>
68 #include <dev/ic/comreg.h>
69 #include <dev/ic/comvar.h>
71 #include <dev/isa/isavar.h>
72 #include <dev/isa/com_multi.h>
77 * Grr. This card always uses 0x420 for the status register, regardless
80 #define STATUS_IOADDR 0x420
81 #define STATUS_SIZE 8 /* May be bogus... */
87 bus_space_tag_t sc_iot
;
90 int sc_alive
; /* mask of slave units attached */
91 void *sc_slaves
[NSLAVES
]; /* com device unit numbers */
92 bus_space_handle_t sc_slaveioh
[NSLAVES
];
93 bus_space_handle_t sc_statusioh
;
96 #define SLAVE_IOBASE_OFFSET 0x108
97 static int slave_iobases
[8] = {
98 0x108, /* port 0, base port */
104 0x200, /* port 7, note address skip... */
108 int addcomprobe(device_t
, cfdata_t
, void *);
109 void addcomattach(device_t
, device_t
, void *);
110 int addcomintr(void *);
112 CFATTACH_DECL(addcom_isa
, sizeof(struct addcom_softc
),
113 addcomprobe
, addcomattach
, NULL
, NULL
);
116 addcomprobe(device_t parent
, cfdata_t self
, void *aux
)
118 struct isa_attach_args
*ia
= aux
;
119 bus_space_tag_t iot
= ia
->ia_iot
;
120 bus_space_handle_t ioh
;
121 int i
, iobase
, rv
= 1;
124 * Do the normal com probe for the first UART and assume
125 * its presence, and the ability to map the other UARTS,
126 * means there is a multiport board there.
127 * XXX Needs more robustness.
135 if (ISA_DIRECT_CONFIG(ia
))
138 /* Disallow wildcarded i/o address. */
139 if (ia
->ia_io
[0].ir_addr
== ISA_UNKNOWN_PORT
)
141 if (ia
->ia_irq
[0].ir_irq
== ISA_UNKNOWN_IRQ
)
144 iobase
= ia
->ia_io
[0].ir_addr
;
146 /* if the first port is in use as console, then it. */
147 if (com_is_console(iot
, iobase
, 0))
150 if (bus_space_map(iot
, iobase
, COM_NPORTS
, 0, &ioh
)) {
154 rv
= comprobe1(iot
, ioh
);
155 bus_space_unmap(iot
, ioh
, COM_NPORTS
);
160 for (i
= 1; i
< NSLAVES
; i
++) {
161 iobase
+= slave_iobases
[i
] - slave_iobases
[i
- 1];
163 if (com_is_console(iot
, iobase
, 0))
166 if (bus_space_map(iot
, iobase
, COM_NPORTS
, 0, &ioh
)) {
170 bus_space_unmap(iot
, ioh
, COM_NPORTS
);
176 ia
->ia_io
[0].ir_size
= NSLAVES
* COM_NPORTS
;
187 addcomattach(device_t parent
, device_t self
, void *aux
)
189 struct addcom_softc
*sc
= (void *)self
;
190 struct isa_attach_args
*ia
= aux
;
191 struct commulti_attach_args ca
;
192 bus_space_tag_t iot
= ia
->ia_iot
;
197 sc
->sc_iot
= ia
->ia_iot
;
198 sc
->sc_iobase
= ia
->ia_io
[0].ir_addr
;
200 if (bus_space_map(iot
, STATUS_IOADDR
, STATUS_SIZE
,
201 0, &sc
->sc_statusioh
)) {
202 aprint_error_dev(&sc
->sc_dev
, "can't map status space\n");
206 for (i
= 0; i
< NSLAVES
; i
++) {
207 iobase
= sc
->sc_iobase
209 - SLAVE_IOBASE_OFFSET
;
210 if (!com_is_console(iot
, iobase
, &sc
->sc_slaveioh
[i
]) &&
211 bus_space_map(iot
, iobase
, COM_NPORTS
, 0,
212 &sc
->sc_slaveioh
[i
])) {
213 aprint_error_dev(&sc
->sc_dev
, "can't map i/o space for slave %d\n", i
);
218 for (i
= 0; i
< NSLAVES
; i
++) {
220 ca
.ca_iot
= sc
->sc_iot
;
221 ca
.ca_ioh
= sc
->sc_slaveioh
[i
];
222 ca
.ca_iobase
= sc
->sc_iobase
224 - SLAVE_IOBASE_OFFSET
;
227 sc
->sc_slaves
[i
] = config_found(self
, &ca
, commultiprint
);
228 if (sc
->sc_slaves
[i
] != NULL
)
229 sc
->sc_alive
|= 1 << i
;
232 sc
->sc_ih
= isa_intr_establish(ia
->ia_ic
, ia
->ia_irq
[0].ir_irq
,
233 IST_EDGE
, IPL_SERIAL
, addcomintr
, sc
);
237 addcomintr(void *arg
)
239 struct addcom_softc
*sc
= arg
;
240 bus_space_tag_t iot
= sc
->sc_iot
;
241 int alive
= sc
->sc_alive
;
244 bits
= bus_space_read_1(iot
, sc
->sc_statusioh
, 0) & alive
;
250 if (bits & (1 << (n))) \
251 comintr(sc->sc_slaves[n]);
261 bits
= bus_space_read_1(iot
, sc
->sc_statusioh
, 0) & alive
;