Line data Source code
1 : /* $OpenBSD: com_pcmcia.c,v 1.57 2017/12/30 20:46:59 guenther Exp $ */
2 : /* $NetBSD: com_pcmcia.c,v 1.15 1998/08/22 17:47:58 msaitoh Exp $ */
3 :
4 : /*
5 : * Copyright (c) 1997 - 1999, Jason Downs. 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. Neither the name(s) of the author(s) nor the name OpenBSD
16 : * may be used to endorse or promote products derived from this software
17 : * without specific prior written permission.
18 : *
19 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
20 : * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 : * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 : * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
23 : * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 : * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 : * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 : * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 : * SUCH DAMAGE.
30 : */
31 : /*-
32 : * Copyright (c) 1998 The NetBSD Foundation, Inc.
33 : * All rights reserved.
34 : *
35 : * This code is derived from software contributed to The NetBSD Foundation
36 : * by Charles M. Hannum.
37 : *
38 : * Redistribution and use in source and binary forms, with or without
39 : * modification, are permitted provided that the following conditions
40 : * are met:
41 : * 1. Redistributions of source code must retain the above copyright
42 : * notice, this list of conditions and the following disclaimer.
43 : * 2. Redistributions in binary form must reproduce the above copyright
44 : * notice, this list of conditions and the following disclaimer in the
45 : * documentation and/or other materials provided with the distribution.
46 : *
47 : * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
48 : * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
49 : * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
50 : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
51 : * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
52 : * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
53 : * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
54 : * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
55 : * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
56 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
57 : * POSSIBILITY OF SUCH DAMAGE.
58 : */
59 :
60 : /*-
61 : * Copyright (c) 1991 The Regents of the University of California.
62 : * All rights reserved.
63 : *
64 : * Redistribution and use in source and binary forms, with or without
65 : * modification, are permitted provided that the following conditions
66 : * are met:
67 : * 1. Redistributions of source code must retain the above copyright
68 : * notice, this list of conditions and the following disclaimer.
69 : * 2. Redistributions in binary form must reproduce the above copyright
70 : * notice, this list of conditions and the following disclaimer in the
71 : * documentation and/or other materials provided with the distribution.
72 : * 3. Neither the name of the University nor the names of its contributors
73 : * may be used to endorse or promote products derived from this software
74 : * without specific prior written permission.
75 : *
76 : * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
77 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
78 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
79 : * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
80 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
81 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
82 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
83 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
84 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
85 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
86 : * SUCH DAMAGE.
87 : *
88 : * @(#)com.c 7.5 (Berkeley) 5/16/91
89 : */
90 :
91 : #include <sys/param.h>
92 : #include <sys/systm.h>
93 : #include <sys/ioctl.h>
94 : #include <sys/selinfo.h>
95 : #include <sys/tty.h>
96 : #include <sys/conf.h>
97 : #include <sys/uio.h>
98 : #include <sys/kernel.h>
99 : #include <sys/syslog.h>
100 : #include <sys/device.h>
101 :
102 : #include <machine/intr.h>
103 :
104 : #include <dev/pcmcia/pcmciavar.h>
105 : #include <dev/pcmcia/pcmciareg.h>
106 : #include <dev/pcmcia/pcmciadevs.h>
107 :
108 : #include "com.h"
109 :
110 : #include <dev/ic/comreg.h>
111 : #include <dev/ic/comvar.h>
112 : #include <dev/ic/ns16550reg.h>
113 :
114 : #include <dev/isa/isareg.h>
115 :
116 : #define com_lcr com_cfcr
117 :
118 : /* Devices that we need to match by CIS strings */
119 : struct com_pcmcia_product {
120 : char *cis1_info[4];
121 : } com_pcmcia_prod[] = {
122 : { PCMCIA_CIS_MEGAHERTZ_XJ2288 },
123 : { PCMCIA_CIS_NOVATEL_NRM6831 },
124 : };
125 :
126 : int com_pcmcia_match(struct device *, void *, void *);
127 : void com_pcmcia_attach(struct device *, struct device *, void *);
128 : int com_pcmcia_detach(struct device *, int);
129 : void com_pcmcia_cleanup(void *);
130 : int com_pcmcia_activate(struct device *, int);
131 :
132 : int com_pcmcia_enable(struct com_softc *);
133 : void com_pcmcia_disable(struct com_softc *);
134 : int com_pcmcia_enable1(struct com_softc *);
135 : void com_pcmcia_disable1(struct com_softc *);
136 :
137 : struct com_pcmcia_softc {
138 : struct com_softc sc_com; /* real "com" softc */
139 :
140 : /* PCMCIA-specific goo */
141 : struct pcmcia_io_handle sc_pcioh; /* PCMCIA i/o space info */
142 : int sc_io_window; /* our i/o window */
143 : struct pcmcia_function *sc_pf; /* our PCMCIA function */
144 : void *sc_ih; /* interrupt handler */
145 : };
146 :
147 : struct cfattach com_pcmcia_ca = {
148 : sizeof(struct com_pcmcia_softc), com_pcmcia_match, com_pcmcia_attach,
149 : com_pcmcia_detach, com_pcmcia_activate
150 : };
151 :
152 : int
153 0 : com_pcmcia_match(parent, match, aux)
154 : struct device *parent;
155 : void *match, *aux;
156 : {
157 0 : struct pcmcia_attach_args *pa = aux;
158 : struct pcmcia_config_entry *cfe;
159 : int i, j, comportmask;
160 :
161 : /* 1. Does it claim to be a serial device? */
162 0 : if (pa->pf->function == PCMCIA_FUNCTION_SERIAL)
163 0 : return 1;
164 :
165 : /* 2. Does it have all four 'standard' port ranges? */
166 : comportmask = 0;
167 0 : SIMPLEQ_FOREACH(cfe, &pa->pf->cfe_head, cfe_list) {
168 0 : switch (cfe->iospace[0].start) {
169 : case IO_COM1:
170 0 : comportmask |= 1;
171 0 : break;
172 : case IO_COM2:
173 0 : comportmask |= 2;
174 0 : break;
175 : case IO_COM3:
176 0 : comportmask |= 4;
177 0 : break;
178 : case IO_COM4:
179 0 : comportmask |= 8;
180 0 : break;
181 : }
182 : }
183 :
184 0 : if (comportmask == 15)
185 0 : return 1;
186 :
187 : /* 3. Is this a card we know about? */
188 0 : for (i = 0; i < nitems(com_pcmcia_prod); i++) {
189 0 : for (j = 0; j < 4; j++)
190 0 : if (com_pcmcia_prod[i].cis1_info[j] &&
191 0 : pa->card->cis1_info[j] &&
192 0 : strcmp(pa->card->cis1_info[j],
193 : com_pcmcia_prod[i].cis1_info[j]))
194 : break;
195 0 : if (j == 4)
196 0 : return 1;
197 : }
198 :
199 0 : return 0;
200 0 : }
201 :
202 : int
203 0 : com_pcmcia_activate(dev, act)
204 : struct device *dev;
205 : int act;
206 : {
207 0 : struct com_pcmcia_softc *sc = (void *) dev;
208 :
209 0 : switch (act) {
210 : case DVACT_SUSPEND:
211 0 : if (sc->sc_ih)
212 0 : pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih);
213 0 : sc->sc_ih = NULL;
214 0 : pcmcia_function_disable(sc->sc_pf);
215 0 : break;
216 : case DVACT_RESUME:
217 0 : pcmcia_function_enable(sc->sc_pf);
218 0 : sc->sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_TTY,
219 0 : comintr, sc, sc->sc_com.sc_dev.dv_xname);
220 0 : com_resume(&sc->sc_com);
221 0 : break;
222 : case DVACT_DEACTIVATE:
223 0 : if (sc->sc_ih)
224 0 : pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih);
225 0 : sc->sc_ih = NULL;
226 0 : pcmcia_function_disable(sc->sc_pf);
227 0 : break;
228 : }
229 0 : return (0);
230 : }
231 :
232 : void
233 0 : com_pcmcia_attach(parent, self, aux)
234 : struct device *parent, *self;
235 : void *aux;
236 : {
237 0 : struct com_pcmcia_softc *psc = (void *) self;
238 0 : struct com_softc *sc = &psc->sc_com;
239 0 : struct pcmcia_attach_args *pa = aux;
240 : struct pcmcia_config_entry *cfe;
241 : const char *intrstr;
242 : int autoalloc = 0;
243 :
244 0 : psc->sc_pf = pa->pf;
245 :
246 : retry:
247 : /* find a cfe we can use */
248 :
249 0 : for (cfe = SIMPLEQ_FIRST(&pa->pf->cfe_head); cfe;
250 0 : cfe = SIMPLEQ_NEXT(cfe, cfe_list)) {
251 : #if 0
252 : /*
253 : * Some modem cards (e.g. Xircom CM33) also have
254 : * mem space. Don't bother with this check.
255 : */
256 : if (cfe->num_memspace != 0)
257 : continue;
258 : #endif
259 :
260 0 : if (cfe->num_iospace != 1)
261 : continue;
262 :
263 0 : if (!pcmcia_io_alloc(pa->pf,
264 : autoalloc ? 0 : cfe->iospace[0].start,
265 : cfe->iospace[0].length, COM_NPORTS, &psc->sc_pcioh)) {
266 : goto found;
267 : }
268 : }
269 0 : if (autoalloc == 0) {
270 : autoalloc = 1;
271 0 : goto retry;
272 0 : } else if (!cfe) {
273 0 : printf(": can't allocate i/o space\n");
274 0 : return;
275 : }
276 :
277 : found:
278 0 : sc->sc_iot = psc->sc_pcioh.iot;
279 0 : sc->sc_ioh = psc->sc_pcioh.ioh;
280 :
281 : /* Enable the card. */
282 0 : pcmcia_function_init(pa->pf, cfe);
283 0 : if (com_pcmcia_enable1(sc))
284 0 : printf(": function enable failed\n");
285 :
286 0 : sc->enabled = 1;
287 :
288 : /* map in the io space */
289 :
290 0 : if (pcmcia_io_map(pa->pf, ((cfe->flags & PCMCIA_CFE_IO16) ?
291 0 : PCMCIA_WIDTH_IO16 : PCMCIA_WIDTH_IO8), 0, psc->sc_pcioh.size,
292 0 : &psc->sc_pcioh, &psc->sc_io_window)) {
293 0 : printf(": can't map i/o space\n");
294 0 : return;
295 : }
296 :
297 0 : printf(" port 0x%lx/%lu", psc->sc_pcioh.addr,
298 0 : (u_long)psc->sc_pcioh.size);
299 :
300 0 : sc->sc_iobase = -1;
301 0 : sc->enable = com_pcmcia_enable;
302 0 : sc->disable = com_pcmcia_disable;
303 0 : sc->sc_frequency = COM_FREQ;
304 :
305 0 : sc->sc_hwflags = 0;
306 0 : sc->sc_swflags = 0;
307 :
308 0 : if (psc->sc_pf->sc->card.manufacturer == PCMCIA_VENDOR_AUDIOVOX &&
309 0 : psc->sc_pf->sc->card.product == PCMCIA_PRODUCT_AUDIOVOX_RTM8000)
310 0 : sc->sc_fifolen = 16;
311 :
312 0 : com_attach_subr(sc);
313 :
314 : /* establish the interrupt. */
315 0 : psc->sc_ih = pcmcia_intr_establish(pa->pf, IPL_TTY, comintr, sc,
316 0 : sc->sc_dev.dv_xname);
317 0 : intrstr = pcmcia_intr_string(psc->sc_pf, psc->sc_ih);
318 0 : if (*intrstr)
319 0 : printf(", %s", intrstr);
320 :
321 : #ifdef notyet
322 : sc->enabled = 0;
323 :
324 : com_pcmcia_disable1(sc);
325 : #endif
326 0 : }
327 :
328 : int
329 0 : com_pcmcia_detach(dev, flags)
330 : struct device *dev;
331 : int flags;
332 : {
333 0 : struct com_pcmcia_softc *psc = (struct com_pcmcia_softc *)dev;
334 : int error;
335 :
336 : /* Release all resources. */
337 0 : error = com_detach(dev, flags);
338 0 : if (error)
339 0 : return (error);
340 :
341 0 : pcmcia_io_unmap(psc->sc_pf, psc->sc_io_window);
342 0 : pcmcia_io_free(psc->sc_pf, &psc->sc_pcioh);
343 :
344 0 : return (0);
345 0 : }
346 :
347 : int
348 0 : com_pcmcia_enable(sc)
349 : struct com_softc *sc;
350 : {
351 0 : struct com_pcmcia_softc *psc = (struct com_pcmcia_softc *) sc;
352 0 : struct pcmcia_function *pf = psc->sc_pf;
353 :
354 : /* establish the interrupt. */
355 0 : psc->sc_ih = pcmcia_intr_establish(pf, IPL_TTY, comintr, sc,
356 0 : sc->sc_dev.dv_xname);
357 0 : if (psc->sc_ih == NULL) {
358 0 : printf("%s: couldn't establish interrupt\n",
359 : sc->sc_dev.dv_xname);
360 0 : return (1);
361 : }
362 0 : return com_pcmcia_enable1(sc);
363 0 : }
364 :
365 : int
366 0 : com_pcmcia_enable1(sc)
367 : struct com_softc *sc;
368 : {
369 0 : struct com_pcmcia_softc *psc = (struct com_pcmcia_softc *) sc;
370 0 : struct pcmcia_function *pf = psc->sc_pf;
371 : int ret;
372 :
373 0 : if ((ret = pcmcia_function_enable(pf)))
374 0 : return(ret);
375 :
376 0 : if ((psc->sc_pf->sc->card.product == PCMCIA_PRODUCT_3COM_3C562) ||
377 0 : (psc->sc_pf->sc->card.product == PCMCIA_PRODUCT_3COM_3CXEM556) ||
378 0 : (psc->sc_pf->sc->card.product == PCMCIA_PRODUCT_3COM_3CXEM556B)) {
379 : int reg;
380 :
381 : /* turn off the ethernet-disable bit */
382 :
383 0 : reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
384 0 : if (reg & 0x08) {
385 0 : reg &= ~0x08;
386 0 : pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
387 0 : }
388 0 : }
389 :
390 0 : return(ret);
391 0 : }
392 :
393 : void
394 0 : com_pcmcia_disable(sc)
395 : struct com_softc *sc;
396 : {
397 0 : struct com_pcmcia_softc *psc = (struct com_pcmcia_softc *) sc;
398 :
399 0 : pcmcia_intr_disestablish(psc->sc_pf, psc->sc_ih);
400 0 : com_pcmcia_disable1(sc);
401 0 : }
402 :
403 : void
404 0 : com_pcmcia_disable1(sc)
405 : struct com_softc *sc;
406 : {
407 0 : struct com_pcmcia_softc *psc = (struct com_pcmcia_softc *) sc;
408 :
409 0 : pcmcia_function_disable(psc->sc_pf);
410 0 : }
|