1*ba9261baSjdolecek /* $NetBSD: com_mca.c,v 1.2 2001/03/31 09:50:14 jdolecek Exp $ */ 21c341b3dSjdolecek 31c341b3dSjdolecek /*- 4*ba9261baSjdolecek * Copyright (c) 2001 The NetBSD Foundation, Inc. 51c341b3dSjdolecek * All rights reserved. 61c341b3dSjdolecek * 71c341b3dSjdolecek * This code is derived from software contributed to The NetBSD Foundation 81c341b3dSjdolecek * by Charles M. Hannum. 91c341b3dSjdolecek * 101c341b3dSjdolecek * Redistribution and use in source and binary forms, with or without 111c341b3dSjdolecek * modification, are permitted provided that the following conditions 121c341b3dSjdolecek * are met: 131c341b3dSjdolecek * 1. Redistributions of source code must retain the above copyright 141c341b3dSjdolecek * notice, this list of conditions and the following disclaimer. 151c341b3dSjdolecek * 2. Redistributions in binary form must reproduce the above copyright 161c341b3dSjdolecek * notice, this list of conditions and the following disclaimer in the 171c341b3dSjdolecek * documentation and/or other materials provided with the distribution. 181c341b3dSjdolecek * 3. All advertising materials mentioning features or use of this software 191c341b3dSjdolecek * must display the following acknowledgement: 201c341b3dSjdolecek * This product includes software developed by the NetBSD 211c341b3dSjdolecek * Foundation, Inc. and its contributors. 221c341b3dSjdolecek * 4. Neither the name of The NetBSD Foundation nor the names of its 231c341b3dSjdolecek * contributors may be used to endorse or promote products derived 241c341b3dSjdolecek * from this software without specific prior written permission. 251c341b3dSjdolecek * 261c341b3dSjdolecek * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 271c341b3dSjdolecek * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 281c341b3dSjdolecek * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 291c341b3dSjdolecek * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 301c341b3dSjdolecek * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 311c341b3dSjdolecek * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 321c341b3dSjdolecek * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 331c341b3dSjdolecek * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 341c341b3dSjdolecek * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 351c341b3dSjdolecek * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 361c341b3dSjdolecek * POSSIBILITY OF SUCH DAMAGE. 371c341b3dSjdolecek */ 381c341b3dSjdolecek 391c341b3dSjdolecek /*- 401c341b3dSjdolecek * Copyright (c) 1991 The Regents of the University of California. 411c341b3dSjdolecek * All rights reserved. 421c341b3dSjdolecek * 431c341b3dSjdolecek * Redistribution and use in source and binary forms, with or without 441c341b3dSjdolecek * modification, are permitted provided that the following conditions 451c341b3dSjdolecek * are met: 461c341b3dSjdolecek * 1. Redistributions of source code must retain the above copyright 471c341b3dSjdolecek * notice, this list of conditions and the following disclaimer. 481c341b3dSjdolecek * 2. Redistributions in binary form must reproduce the above copyright 491c341b3dSjdolecek * notice, this list of conditions and the following disclaimer in the 501c341b3dSjdolecek * documentation and/or other materials provided with the distribution. 511c341b3dSjdolecek * 3. All advertising materials mentioning features or use of this software 521c341b3dSjdolecek * must display the following acknowledgement: 531c341b3dSjdolecek * This product includes software developed by the University of 541c341b3dSjdolecek * California, Berkeley and its contributors. 551c341b3dSjdolecek * 4. Neither the name of the University nor the names of its contributors 561c341b3dSjdolecek * may be used to endorse or promote products derived from this software 571c341b3dSjdolecek * without specific prior written permission. 581c341b3dSjdolecek * 591c341b3dSjdolecek * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 601c341b3dSjdolecek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 611c341b3dSjdolecek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 621c341b3dSjdolecek * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 631c341b3dSjdolecek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 641c341b3dSjdolecek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 651c341b3dSjdolecek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 661c341b3dSjdolecek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 671c341b3dSjdolecek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 681c341b3dSjdolecek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 691c341b3dSjdolecek * SUCH DAMAGE. 701c341b3dSjdolecek * 711c341b3dSjdolecek * @(#)com.c 7.5 (Berkeley) 5/16/91 721c341b3dSjdolecek */ 731c341b3dSjdolecek 741c341b3dSjdolecek /* 751c341b3dSjdolecek * This driver attaches serial port boards and internal modems. 761c341b3dSjdolecek */ 771c341b3dSjdolecek 781c341b3dSjdolecek #include <sys/param.h> 791c341b3dSjdolecek #include <sys/systm.h> 801c341b3dSjdolecek #include <sys/ioctl.h> 811c341b3dSjdolecek #include <sys/select.h> 821c341b3dSjdolecek #include <sys/tty.h> 831c341b3dSjdolecek #include <sys/proc.h> 841c341b3dSjdolecek #include <sys/user.h> 851c341b3dSjdolecek #include <sys/file.h> 861c341b3dSjdolecek #include <sys/uio.h> 871c341b3dSjdolecek #include <sys/kernel.h> 881c341b3dSjdolecek #include <sys/syslog.h> 891c341b3dSjdolecek #include <sys/types.h> 901c341b3dSjdolecek #include <sys/device.h> 911c341b3dSjdolecek 921c341b3dSjdolecek #include <machine/intr.h> 931c341b3dSjdolecek #include <machine/bus.h> 941c341b3dSjdolecek 951c341b3dSjdolecek #include <dev/ic/comreg.h> 961c341b3dSjdolecek #include <dev/ic/comvar.h> 971c341b3dSjdolecek 981c341b3dSjdolecek #include <dev/mca/mcavar.h> 991c341b3dSjdolecek #include <dev/mca/mcadevs.h> 1001c341b3dSjdolecek 1011c341b3dSjdolecek struct com_mca_softc { 1021c341b3dSjdolecek struct com_softc sc_com; /* real "com" softc */ 1031c341b3dSjdolecek 1041c341b3dSjdolecek /* MCA-specific goo. */ 1051c341b3dSjdolecek void *sc_ih; /* interrupt handler */ 1061c341b3dSjdolecek }; 1071c341b3dSjdolecek 1081c341b3dSjdolecek int com_mca_probe __P((struct device *, struct cfdata *, void *)); 1091c341b3dSjdolecek void com_mca_attach __P((struct device *, struct device *, void *)); 1101c341b3dSjdolecek void com_mca_cleanup __P((void *)); 1111c341b3dSjdolecek static int ibm_modem_getcfg __P((struct mca_attach_args *, int *, int *)); 1121c341b3dSjdolecek 1131c341b3dSjdolecek struct cfattach com_mca_ca = { 1141c341b3dSjdolecek sizeof(struct com_mca_softc), com_mca_probe, com_mca_attach 1151c341b3dSjdolecek }; 1161c341b3dSjdolecek 1171c341b3dSjdolecek static const struct com_mca_product { 1181c341b3dSjdolecek u_int32_t cp_prodid; /* MCA product ID */ 1191c341b3dSjdolecek const char *cp_name; /* device name */ 1201c341b3dSjdolecek int (*cp_getcfg) __P((struct mca_attach_args *, int *iobase, int *irq)); 1211c341b3dSjdolecek /* get device i/o base and irq */ 1221c341b3dSjdolecek } com_mca_products[] = { 1231c341b3dSjdolecek { MCA_PRODUCT_IBM_MOD, "IBM Internal Modem", ibm_modem_getcfg }, 1241c341b3dSjdolecek { 0, NULL, NULL }, 1251c341b3dSjdolecek }; 1261c341b3dSjdolecek 1271c341b3dSjdolecek static const struct com_mca_product *com_mca_lookup __P((int)); 1281c341b3dSjdolecek 1291c341b3dSjdolecek static const struct com_mca_product * 1301c341b3dSjdolecek com_mca_lookup(ma_id) 1311c341b3dSjdolecek int ma_id; 1321c341b3dSjdolecek { 1331c341b3dSjdolecek const struct com_mca_product *cpp; 1341c341b3dSjdolecek 1351c341b3dSjdolecek for (cpp = com_mca_products; cpp->cp_name != NULL; cpp++) 1361c341b3dSjdolecek if (cpp->cp_prodid == ma_id) 1371c341b3dSjdolecek return (cpp); 1381c341b3dSjdolecek 1391c341b3dSjdolecek return (NULL); 1401c341b3dSjdolecek } 1411c341b3dSjdolecek 1421c341b3dSjdolecek int 1431c341b3dSjdolecek com_mca_probe(parent, match, aux) 1441c341b3dSjdolecek struct device *parent; 1451c341b3dSjdolecek struct cfdata *match; 1461c341b3dSjdolecek void *aux; 1471c341b3dSjdolecek { 1481c341b3dSjdolecek struct mca_attach_args *ma = aux; 1491c341b3dSjdolecek 1501c341b3dSjdolecek if (com_mca_lookup(ma->ma_id)) 1511c341b3dSjdolecek return (1); 1521c341b3dSjdolecek 1531c341b3dSjdolecek return (0); 1541c341b3dSjdolecek } 1551c341b3dSjdolecek 1561c341b3dSjdolecek void 1571c341b3dSjdolecek com_mca_attach(parent, self, aux) 1581c341b3dSjdolecek struct device *parent, *self; 1591c341b3dSjdolecek void *aux; 1601c341b3dSjdolecek { 1611c341b3dSjdolecek struct com_mca_softc *isc = (void *)self; 1621c341b3dSjdolecek struct com_softc *sc = &isc->sc_com; 1631c341b3dSjdolecek int iobase, irq; 1641c341b3dSjdolecek struct mca_attach_args *ma = aux; 1651c341b3dSjdolecek const struct com_mca_product *cpp; 1661c341b3dSjdolecek 1671c341b3dSjdolecek cpp = com_mca_lookup(ma->ma_id); 1681c341b3dSjdolecek 1691c341b3dSjdolecek /* get iobase and irq */ 1701c341b3dSjdolecek if ((*cpp->cp_getcfg)(ma, &iobase, &irq)) { 1711c341b3dSjdolecek printf(": com_mca_attach: could not get config\n"); 1721c341b3dSjdolecek return; 1731c341b3dSjdolecek } 1741c341b3dSjdolecek 1751c341b3dSjdolecek printf(" slot %d i/o %#x-%#x irq %d: %s\n", ma->ma_slot + 1, 1761c341b3dSjdolecek iobase, iobase + COM_NPORTS - 1, 1771c341b3dSjdolecek irq, cpp->cp_name); 1781c341b3dSjdolecek 1791c341b3dSjdolecek printf("%s", sc->sc_dev.dv_xname); 1801c341b3dSjdolecek 1811c341b3dSjdolecek if (bus_space_map(ma->ma_iot, iobase, COM_NPORTS, 0, &sc->sc_ioh)) { 1821c341b3dSjdolecek printf(": can't map i/o space\n"); 1831c341b3dSjdolecek return; 1841c341b3dSjdolecek } 1851c341b3dSjdolecek 1861c341b3dSjdolecek sc->sc_frequency = COM_FREQ; 1871c341b3dSjdolecek sc->sc_iot = ma->ma_iot; 1881c341b3dSjdolecek sc->sc_iobase = iobase; 1891c341b3dSjdolecek 1901c341b3dSjdolecek com_attach_subr(sc); 1911c341b3dSjdolecek 1921c341b3dSjdolecek isc->sc_ih = mca_intr_establish(ma->ma_mc, irq, IPL_SERIAL, 1931c341b3dSjdolecek comintr, sc); 1941c341b3dSjdolecek if (isc->sc_ih == NULL) { 1951c341b3dSjdolecek printf("%s: couldn't establish interrupt handler\n", 1961c341b3dSjdolecek sc->sc_dev.dv_xname); 1971c341b3dSjdolecek return; 1981c341b3dSjdolecek } 1991c341b3dSjdolecek 2001c341b3dSjdolecek /* 2011c341b3dSjdolecek * Shutdown hook for buggy BIOSs that don't recognize the UART 2021c341b3dSjdolecek * without a disabled FIFO. 2031c341b3dSjdolecek * XXX is this necessary on MCA ? --- jdolecek 2041c341b3dSjdolecek */ 2051c341b3dSjdolecek if (shutdownhook_establish(com_mca_cleanup, sc) == NULL) 2061c341b3dSjdolecek panic("com_mca_attach: could not establish shutdown hook"); 2071c341b3dSjdolecek } 2081c341b3dSjdolecek 2091c341b3dSjdolecek void 2101c341b3dSjdolecek com_mca_cleanup(arg) 2111c341b3dSjdolecek void *arg; 2121c341b3dSjdolecek { 2131c341b3dSjdolecek struct com_softc *sc = arg; 2141c341b3dSjdolecek 2151c341b3dSjdolecek if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) 2161c341b3dSjdolecek bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_fifo, 0); 2171c341b3dSjdolecek } 2181c341b3dSjdolecek 2191c341b3dSjdolecek /* map serial_X to iobase and irq */ 2201c341b3dSjdolecek static const struct { 2211c341b3dSjdolecek int iobase; 2221c341b3dSjdolecek int irq; 2231c341b3dSjdolecek } MCA_SERIAL[] = { 2241c341b3dSjdolecek { 0x03f8, 4 }, /* SERIAL_1 */ 2251c341b3dSjdolecek { 0x02f8, 3 }, /* SERIAL_2 */ 2261c341b3dSjdolecek { 0x3220, 3 }, /* SERIAL_3 */ 2271c341b3dSjdolecek { 0x3228, 3 }, /* SERIAL_4 */ 2281c341b3dSjdolecek { 0x4220, 3 }, /* SERIAL_5 */ 2291c341b3dSjdolecek { 0x4228, 3 }, /* SERIAL_6 */ 2301c341b3dSjdolecek { 0x5220, 3 }, /* SERIAL_7 */ 2311c341b3dSjdolecek { 0x5228, 3 }, /* SERIAL_8 */ 2321c341b3dSjdolecek }; 2331c341b3dSjdolecek 2341c341b3dSjdolecek /* 2351c341b3dSjdolecek * Get config for IBM Internal Modem (ID 0xEDFF). This beast doesn't 2361c341b3dSjdolecek * seem to support even AT commands, it's good as example for adding 2371c341b3dSjdolecek * other stuff though. 2381c341b3dSjdolecek */ 2391c341b3dSjdolecek static int 2401c341b3dSjdolecek ibm_modem_getcfg(ma, iobasep, irqp) 2411c341b3dSjdolecek struct mca_attach_args *ma; 2421c341b3dSjdolecek int *iobasep, *irqp; 2431c341b3dSjdolecek { 2441c341b3dSjdolecek int pos2; 2451c341b3dSjdolecek int snum; 2461c341b3dSjdolecek 2471c341b3dSjdolecek pos2 = mca_conf_read(ma->ma_mc, ma->ma_slot, 2); 2481c341b3dSjdolecek 2491c341b3dSjdolecek /* 2501c341b3dSjdolecek * POS register 2: (adf pos0) 2511c341b3dSjdolecek * 7 6 5 4 3 2 1 0 2521c341b3dSjdolecek * \__/ \__ enable: 0=adapter disabled, 1=adapter enabled 2531c341b3dSjdolecek * \_____ Serial Configuration: XX=SERIAL_XX 2541c341b3dSjdolecek */ 2551c341b3dSjdolecek 2561c341b3dSjdolecek snum = (pos2 & 0x0e) >> 1; 2571c341b3dSjdolecek 2581c341b3dSjdolecek *iobasep = MCA_SERIAL[snum].iobase; 2591c341b3dSjdolecek *irqp = MCA_SERIAL[snum].irq; 2601c341b3dSjdolecek 2611c341b3dSjdolecek return (0); 2621c341b3dSjdolecek } 263