1 /* $OpenBSD: com_cardbus.c,v 1.12 2005/06/29 18:22:49 deraadt Exp $ */
2 /* $NetBSD: com_cardbus.c,v 1.4 2000/04/17 09:21:59 joda Exp $ */
3 
4 /*
5  * Copyright (c) 2000 Johan Danielsson
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * 3. Neither the name of author nor the names of any contributors may
20  *    be used to endorse or promote products derived from this
21  *    software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
27  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 /* This is a driver for CardBus based serial devices. It is less
37    generic than it could be, but it keeps the complexity down. So far
38    it assumes that anything that reports itself as a `serial' device
39    is infact a 16x50 or 8250, which is not necessarily true (in
40    practice this shouldn't be a problem). It also does not handle
41    devices in the `multiport serial' or `modem' sub-classes, I've
42    never seen any of these, so I don't know what they might look like.
43 
44    If the CardBus device only has one BAR (that is not also the CIS
45    BAR) listed in the CIS, it is assumed to be the one to use. For
46    devices with more than one BAR, the list of known devies has to be
47    updated below.  */
48 
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/tty.h>
52 #include <sys/device.h>
53 
54 #include <dev/cardbus/cardbusvar.h>
55 #include <dev/pci/pcidevs.h>
56 
57 #include <dev/pcmcia/pcmciareg.h>
58 
59 #include <dev/isa/isavar.h>
60 
61 #include "com.h"
62 #ifdef i386
63 #include "pccom.h"
64 #endif
65 
66 #include <dev/ic/comreg.h>
67 #if NPCCOM > 0
68 #include <i386/isa/pccomvar.h>
69 #endif
70 #if NCOM > 0
71 #include <dev/ic/comvar.h>
72 #endif
73 #include <dev/ic/ns16550reg.h>
74 
75 #define	com_lcr		com_cfcr
76 
77 struct com_cardbus_softc {
78 	struct com_softc	cc_com;
79 	void			*cc_ih;
80 	cardbus_devfunc_t	cc_ct;
81 	bus_addr_t		cc_addr;
82 	cardbusreg_t		cc_base;
83 	bus_size_t		cc_size;
84 	cardbusreg_t		cc_csr;
85 	int			cc_cben;
86 	cardbustag_t		cc_tag;
87 	cardbusreg_t		cc_reg;
88 	int			cc_type;
89 };
90 
91 #define DEVNAME(CSC) ((CSC)->cc_com.sc_dev.dv_xname)
92 
93 int	com_cardbus_match(struct device *, void *, void *);
94 void	com_cardbus_attach(struct device *, struct device *, void *);
95 int	com_cardbus_detach(struct device *, int);
96 
97 void	com_cardbus_setup(struct com_cardbus_softc *);
98 int	com_cardbus_enable(struct com_softc *);
99 void	com_cardbus_disable(struct com_softc *);
100 struct csdev *com_cardbus_find_csdev(struct cardbus_attach_args *);
101 int	com_cardbus_gofigure(struct cardbus_attach_args *,
102     struct com_cardbus_softc *);
103 void	com_cardbus_attach2(struct com_softc *);
104 
105 #if NCOM_CARDBUS
106 struct cfattach com_cardbus_ca = {
107 	sizeof(struct com_cardbus_softc), com_cardbus_match,
108 	com_cardbus_attach, com_cardbus_detach, com_activate
109 };
110 #elif NPCCOM_CARDBUS
111 struct cfattach pccom_cardbus_ca = {
112 	sizeof(struct com_cardbus_softc), com_cardbus_match,
113 	com_cardbus_attach, com_cardbus_detach, com_activate
114 };
115 #endif
116 
117 static struct csdev {
118 	int		vendor;
119 	int		product;
120 	cardbusreg_t	reg;
121 	int		type;
122 } csdevs[] = {
123 	{ PCI_VENDOR_XIRCOM, PCI_PRODUCT_XIRCOM_MODEM56,
124 	  CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO },
125 	{ PCI_VENDOR_XIRCOM, PCI_PRODUCT_XIRCOM_CBEM56G,
126 	  CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO },
127 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_MODEM56,
128 	  CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO },
129 	{ PCI_VENDOR_3COM, PCI_PRODUCT_3COM_MODEM56,
130 	  CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO },
131 	{ PCI_VENDOR_3COM, PCI_PRODUCT_3COM_GLOBALMODEM56,
132 	  CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO },
133 	{ PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_SERIAL,
134 	  CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO }
135 };
136 
137 static const int ncsdevs = sizeof(csdevs) / sizeof(csdevs[0]);
138 
139 struct csdev*
com_cardbus_find_csdev(struct cardbus_attach_args * ca)140 com_cardbus_find_csdev(struct cardbus_attach_args *ca)
141 {
142 	struct csdev *cp;
143 
144 	for (cp = csdevs; cp < csdevs + ncsdevs; cp++)
145 		if (cp->vendor == CARDBUS_VENDOR(ca->ca_id) &&
146 		    cp->product == CARDBUS_PRODUCT(ca->ca_id))
147 			return (cp);
148 	return (NULL);
149 }
150 
151 int
com_cardbus_match(struct device * parent,void * match,void * aux)152 com_cardbus_match(struct device *parent, void *match, void *aux)
153 {
154 	struct cardbus_attach_args *ca = aux;
155 
156 	/* known devices are ok */
157 	if (com_cardbus_find_csdev(ca) != NULL)
158 	    return (10);
159 
160 	/* as are serial devices with a known UART */
161 	if (ca->ca_cis.funcid == PCMCIA_FUNCTION_SERIAL &&
162 	    ca->ca_cis.funce.serial.uart_present != 0 &&
163 	    (ca->ca_cis.funce.serial.uart_type == 0 ||	/* 8250 */
164 	    ca->ca_cis.funce.serial.uart_type == 1 ||	/* 16450 */
165 	    ca->ca_cis.funce.serial.uart_type == 2))	/* 16550 */
166 	    return (1);
167 
168 	return (0);
169 }
170 
171 int
com_cardbus_gofigure(struct cardbus_attach_args * ca,struct com_cardbus_softc * csc)172 com_cardbus_gofigure(struct cardbus_attach_args *ca,
173     struct com_cardbus_softc *csc)
174 {
175 	int i, index = -1;
176 	cardbusreg_t cis_ptr;
177 	struct csdev *cp;
178 
179 	/* If this device is listed above, use the known values, */
180 	cp = com_cardbus_find_csdev(ca);
181 	if (cp != NULL) {
182 		csc->cc_reg = cp->reg;
183 		csc->cc_type = cp->type;
184 		return (0);
185 	}
186 
187 	cis_ptr = Cardbus_conf_read(csc->cc_ct, csc->cc_tag, CARDBUS_CIS_REG);
188 
189 	/* otherwise try to deduce which BAR and type to use from CIS.  If
190 	   there is only one BAR, it must be the one we should use, if
191 	   there are more, we're out of luck.  */
192 	for (i = 0; i < 7; i++) {
193 		/* ignore zero sized BARs */
194 		if (ca->ca_cis.bar[i].size == 0)
195 			continue;
196 		/* ignore the CIS BAR */
197 		if (CARDBUS_CIS_ASI_BAR(cis_ptr) ==
198 		    CARDBUS_CIS_ASI_BAR(ca->ca_cis.bar[i].flags))
199 			continue;
200 		if (index != -1)
201 			goto multi_bar;
202 		index = i;
203 	}
204 	if (index == -1) {
205 		printf(": couldn't find any base address tuple\n");
206 		return (1);
207 	}
208 	csc->cc_reg = CARDBUS_CIS_ASI_BAR(ca->ca_cis.bar[index].flags);
209 	if ((ca->ca_cis.bar[index].flags & 0x10) == 0)
210 		csc->cc_type = CARDBUS_MAPREG_TYPE_MEM;
211 	else
212 		csc->cc_type = CARDBUS_MAPREG_TYPE_IO;
213 	return (0);
214 
215   multi_bar:
216 	printf(": there are more than one possible base\n");
217 
218 	printf("%s: address for this device, "
219 	    "please report the following information\n",
220 	    DEVNAME(csc));
221 	printf("%s: vendor 0x%x product 0x%x\n", DEVNAME(csc),
222 	    CARDBUS_VENDOR(ca->ca_id), CARDBUS_PRODUCT(ca->ca_id));
223 	for (i = 0; i < 7; i++) {
224 		/* ignore zero sized BARs */
225 		if (ca->ca_cis.bar[i].size == 0)
226 			continue;
227 		/* ignore the CIS BAR */
228 		if (CARDBUS_CIS_ASI_BAR(cis_ptr) ==
229 		    CARDBUS_CIS_ASI_BAR(ca->ca_cis.bar[i].flags))
230 			continue;
231 		printf("%s: base address %x type %s size %x\n",
232 		    DEVNAME(csc), CARDBUS_CIS_ASI_BAR(ca->ca_cis.bar[i].flags),
233 		    (ca->ca_cis.bar[i].flags & 0x10) ? "i/o" : "mem",
234 		    ca->ca_cis.bar[i].size);
235 	}
236 	return (1);
237 }
238 
239 void
com_cardbus_attach(struct device * parent,struct device * self,void * aux)240 com_cardbus_attach(struct device *parent, struct device *self, void *aux)
241 {
242 	struct com_softc *sc = (struct com_softc*)self;
243 	struct com_cardbus_softc *csc = (struct com_cardbus_softc*)self;
244 	struct cardbus_attach_args *ca = aux;
245 
246 	csc->cc_ct = ca->ca_ct;
247 	csc->cc_tag = Cardbus_make_tag(csc->cc_ct);
248 
249 	if (com_cardbus_gofigure(ca, csc) != 0)
250 		return;
251 
252 	if (Cardbus_mapreg_map(ca->ca_ct, csc->cc_reg, csc->cc_type, 0,
253 	    &sc->sc_iot, &sc->sc_ioh, &csc->cc_addr, &csc->cc_size) != 0) {
254 		printf("failed to map memory");
255 		return;
256 	}
257 
258 	csc->cc_base = csc->cc_addr;
259 	csc->cc_csr = CARDBUS_COMMAND_MASTER_ENABLE;
260 	if (csc->cc_type == CARDBUS_MAPREG_TYPE_IO) {
261 		csc->cc_base |= CARDBUS_MAPREG_TYPE_IO;
262 		csc->cc_csr |= CARDBUS_COMMAND_IO_ENABLE;
263 		csc->cc_cben = CARDBUS_IO_ENABLE;
264 	} else {
265 		csc->cc_csr |= CARDBUS_COMMAND_MEM_ENABLE;
266 		csc->cc_cben = CARDBUS_MEM_ENABLE;
267 	}
268 
269 	sc->sc_iobase = csc->cc_addr;
270 	sc->sc_frequency = COM_FREQ;
271 
272 	timeout_set(&sc->sc_dtr_tmo, com_raisedtr, sc);
273 	timeout_set(&sc->sc_diag_tmo, comdiag, sc);
274 
275 	sc->enable = com_cardbus_enable;
276 	sc->disable = com_cardbus_disable;
277 	sc->enabled = 0;
278 
279 	if (ca->ca_cis.cis1_info[0] && ca->ca_cis.cis1_info[1]) {
280 		printf(": %s %s\n", ca->ca_cis.cis1_info[0],
281 		    ca->ca_cis.cis1_info[1]);
282 		printf("%s", DEVNAME(csc));
283 	}
284 
285 	if (com_cardbus_enable(sc))
286 		printf(": function enable failed\n");
287 	sc->enabled = 1;
288 	com_cardbus_attach2(sc);
289 }
290 
291 void
com_cardbus_setup(struct com_cardbus_softc * csc)292 com_cardbus_setup(struct com_cardbus_softc *csc)
293 {
294         cardbus_devfunc_t ct = csc->cc_ct;
295         cardbus_chipset_tag_t cc = ct->ct_cc;
296         cardbus_function_tag_t cf = ct->ct_cf;
297 	cardbusreg_t reg;
298 
299 	Cardbus_conf_write(ct, csc->cc_tag, csc->cc_reg, csc->cc_base);
300 
301 	/* enable accesses on cardbus bridge */
302 	cf->cardbus_ctrl(cc, csc->cc_cben);
303 	cf->cardbus_ctrl(cc, CARDBUS_BM_ENABLE);
304 
305 	/* and the card itself */
306 	reg = Cardbus_conf_read(ct, csc->cc_tag, CARDBUS_COMMAND_STATUS_REG);
307 	reg &= ~(CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MEM_ENABLE);
308 	reg |= csc->cc_csr;
309 	Cardbus_conf_write(ct, csc->cc_tag, CARDBUS_COMMAND_STATUS_REG, reg);
310 
311         /*
312          * Make sure the latency timer is set to some reasonable
313          * value.
314          */
315         reg = cardbus_conf_read(cc, cf, csc->cc_tag, CARDBUS_BHLC_REG);
316         if (CARDBUS_LATTIMER(reg) < 0x20) {
317                 reg &= ~(CARDBUS_LATTIMER_MASK << CARDBUS_LATTIMER_SHIFT);
318                 reg |= (0x20 << CARDBUS_LATTIMER_SHIFT);
319                 cardbus_conf_write(cc, cf, csc->cc_tag, CARDBUS_BHLC_REG, reg);
320         }
321 }
322 
323 int
com_cardbus_enable(struct com_softc * sc)324 com_cardbus_enable(struct com_softc *sc)
325 {
326 	struct com_cardbus_softc *csc = (struct com_cardbus_softc*)sc;
327 	struct cardbus_softc *psc =
328 	    (struct cardbus_softc *)sc->sc_dev.dv_parent;
329 	cardbus_chipset_tag_t cc = psc->sc_cc;
330 	cardbus_function_tag_t cf = psc->sc_cf;
331 
332 	Cardbus_function_enable(csc->cc_ct);
333 
334 	com_cardbus_setup(csc);
335 
336 	/* establish the interrupt. */
337 	csc->cc_ih = cardbus_intr_establish(cc, cf, psc->sc_intrline,
338 	    IPL_TTY, comintr, sc);
339 	if (csc->cc_ih == NULL) {
340 		printf("%s: couldn't establish interrupt\n", DEVNAME(csc));
341 		return (1);
342 	}
343 
344 	printf(": irq %d,", psc->sc_intrline);
345 
346 	return (0);
347 }
348 
349 void
com_cardbus_disable(struct com_softc * sc)350 com_cardbus_disable(struct com_softc *sc)
351 {
352 	struct com_cardbus_softc *csc = (struct com_cardbus_softc*)sc;
353 	struct cardbus_softc *psc =
354 	    (struct cardbus_softc *)sc->sc_dev.dv_parent;
355 	cardbus_chipset_tag_t cc = psc->sc_cc;
356 	cardbus_function_tag_t cf = psc->sc_cf;
357 
358 	cardbus_intr_disestablish(cc, cf, csc->cc_ih);
359 	Cardbus_function_disable(csc->cc_ct);
360 }
361 
362 int
com_cardbus_detach(struct device * self,int flags)363 com_cardbus_detach(struct device *self, int flags)
364 {
365 	struct com_cardbus_softc *csc = (struct com_cardbus_softc *) self;
366 	struct com_softc *sc = (struct com_softc *) self;
367 	struct cardbus_softc *psc = (struct cardbus_softc *)self->dv_parent;
368 	int error;
369 
370 	if ((error = com_detach(self, flags)) != 0)
371 		return (error);
372 
373 	cardbus_intr_disestablish(psc->sc_cc, psc->sc_cf, csc->cc_ih);
374 
375 	Cardbus_mapreg_unmap(csc->cc_ct, csc->cc_reg, sc->sc_iot, sc->sc_ioh,
376 	    csc->cc_size);
377 
378 	return (0);
379 }
380 
381 
382 /*
383  * XXX This should be handled by a generic attach
384  */
385 void
com_cardbus_attach2(sc)386 com_cardbus_attach2(sc)
387 	struct com_softc *sc;
388 {
389 	bus_space_tag_t iot = sc->sc_iot;
390 	bus_space_handle_t ioh = sc->sc_ioh;
391 	u_int8_t lcr;
392 
393 	sc->sc_hwflags = 0;
394 	sc->sc_swflags = 0;
395 
396 	/*
397 	 * Probe for all known forms of UART.
398 	 */
399 	lcr = bus_space_read_1(iot, ioh, com_lcr);
400 
401 	bus_space_write_1(iot, ioh, com_lcr, LCR_EFR);
402 	bus_space_write_1(iot, ioh, com_efr, 0);
403 	bus_space_write_1(iot, ioh, com_lcr, 0);
404 
405 	bus_space_write_1(iot, ioh, com_fifo, FIFO_ENABLE);
406 	delay(100);
407 
408 	switch(bus_space_read_1(iot, ioh, com_iir) >> 6) {
409 	case 0:
410 		sc->sc_uarttype = COM_UART_16450;
411 		break;
412 	case 2:
413 		sc->sc_uarttype = COM_UART_16550;
414 		break;
415 	case 3:
416 		sc->sc_uarttype = COM_UART_16550A;
417 		break;
418 	default:
419 		sc->sc_uarttype = COM_UART_UNKNOWN;
420 		break;
421 	}
422 
423 	if (sc->sc_uarttype == COM_UART_16550A) { /* Probe for ST16650s */
424 		bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB);
425 		if (bus_space_read_1(iot, ioh, com_efr) == 0) {
426 			sc->sc_uarttype = COM_UART_ST16650;
427 		} else {
428 			bus_space_write_1(iot, ioh, com_lcr, LCR_EFR);
429 			if (bus_space_read_1(iot, ioh, com_efr) == 0)
430 				sc->sc_uarttype = COM_UART_ST16650V2;
431 		}
432 	}
433 
434 #if NPCCOM > 0
435 #ifdef i386
436 	if (sc->sc_uarttype == COM_UART_ST16650V2) {	/* Probe for XR16850s */
437 		u_int8_t dlbl, dlbh;
438 
439 		/* Enable latch access and get the current values. */
440 		bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB);
441 		dlbl = bus_space_read_1(iot, ioh, com_dlbl);
442 		dlbh = bus_space_read_1(iot, ioh, com_dlbh);
443 
444 		/* Zero out the latch divisors */
445 		bus_space_write_1(iot, ioh, com_dlbl, 0);
446 		bus_space_write_1(iot, ioh, com_dlbh, 0);
447 
448 		if (bus_space_read_1(iot, ioh, com_dlbh) == 0x10) {
449 			sc->sc_uarttype = COM_UART_XR16850;
450 			sc->sc_uartrev = bus_space_read_1(iot, ioh, com_dlbl);
451 		}
452 
453 		/* Reset to original. */
454 		bus_space_write_1(iot, ioh, com_dlbl, dlbl);
455 		bus_space_write_1(iot, ioh, com_dlbh, dlbh);
456 	}
457 #endif
458 #endif
459 
460 	/* Reset the LCR (latch access is probably enabled). */
461 	bus_space_write_1(iot, ioh, com_lcr, lcr);
462 	if (sc->sc_uarttype == COM_UART_16450) { /* Probe for 8250 */
463 		u_int8_t scr0, scr1, scr2;
464 
465 		scr0 = bus_space_read_1(iot, ioh, com_scratch);
466 		bus_space_write_1(iot, ioh, com_scratch, 0xa5);
467 		scr1 = bus_space_read_1(iot, ioh, com_scratch);
468 		bus_space_write_1(iot, ioh, com_scratch, 0x5a);
469 		scr2 = bus_space_read_1(iot, ioh, com_scratch);
470 		bus_space_write_1(iot, ioh, com_scratch, scr0);
471 
472 		if ((scr1 != 0xa5) || (scr2 != 0x5a))
473 			sc->sc_uarttype = COM_UART_8250;
474 	}
475 
476 	/*
477 	 * Print UART type and initialize ourself.
478 	 */
479 	sc->sc_fifolen = 1;	/* default */
480 	printf(" ");
481 	switch (sc->sc_uarttype) {
482 	case COM_UART_UNKNOWN:
483 		printf("unknown uart\n");
484 		break;
485 	case COM_UART_8250:
486 		printf("ns8250, no fifo\n");
487 		break;
488 	case COM_UART_16450:
489 		printf("ns16450, no fifo\n");
490 		break;
491 	case COM_UART_16550:
492 		printf("ns16550, no working fifo\n");
493 		break;
494 	case COM_UART_16550A:
495 		printf("ns16550a, 16 byte fifo\n");
496 		SET(sc->sc_hwflags, COM_HW_FIFO);
497 		sc->sc_fifolen = 16;
498 		break;
499 	case COM_UART_ST16650:
500 		printf("st16650, no working fifo\n");
501 		break;
502 	case COM_UART_ST16650V2:
503 		printf("st16650, 32 byte fifo\n");
504 		SET(sc->sc_hwflags, COM_HW_FIFO);
505 		sc->sc_fifolen = 32;
506 		break;
507 #if NPCCOM > 0
508 #ifdef i386
509 	case COM_UART_XR16850:
510 		printf("xr16850 (rev %d), 128 byte fifo\n", sc->sc_uartrev);
511 		SET(sc->sc_hwflags, COM_HW_FIFO);
512 		sc->sc_fifolen = 128;
513 		break;
514 #endif
515 #endif
516 	default:
517 		panic("comattach: bad fifo type");
518 	}
519 
520 	/* clear and disable fifo */
521 	bus_space_write_1(iot, ioh, com_fifo, FIFO_RCV_RST | FIFO_XMT_RST);
522 	(void)bus_space_read_1(iot, ioh, com_data);
523 	bus_space_write_1(iot, ioh, com_fifo, 0);
524 }
525