Home | History | Annotate | Line # | Download | only in mca
com_mca.c revision 1.17.28.1
      1  1.17.28.1    bouyer /*	$NetBSD: com_mca.c,v 1.17.28.1 2007/10/25 22:38:36 bouyer Exp $	*/
      2        1.1  jdolecek 
      3        1.1  jdolecek /*-
      4        1.2  jdolecek  * Copyright (c) 2001 The NetBSD Foundation, Inc.
      5        1.1  jdolecek  * All rights reserved.
      6        1.1  jdolecek  *
      7        1.1  jdolecek  * This code is derived from software contributed to The NetBSD Foundation
      8        1.1  jdolecek  * by Charles M. Hannum.
      9        1.1  jdolecek  *
     10        1.1  jdolecek  * Redistribution and use in source and binary forms, with or without
     11        1.1  jdolecek  * modification, are permitted provided that the following conditions
     12        1.1  jdolecek  * are met:
     13        1.1  jdolecek  * 1. Redistributions of source code must retain the above copyright
     14        1.1  jdolecek  *    notice, this list of conditions and the following disclaimer.
     15        1.1  jdolecek  * 2. Redistributions in binary form must reproduce the above copyright
     16        1.1  jdolecek  *    notice, this list of conditions and the following disclaimer in the
     17        1.1  jdolecek  *    documentation and/or other materials provided with the distribution.
     18        1.1  jdolecek  * 3. All advertising materials mentioning features or use of this software
     19        1.1  jdolecek  *    must display the following acknowledgement:
     20        1.1  jdolecek  *        This product includes software developed by the NetBSD
     21        1.1  jdolecek  *        Foundation, Inc. and its contributors.
     22        1.1  jdolecek  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23        1.1  jdolecek  *    contributors may be used to endorse or promote products derived
     24        1.1  jdolecek  *    from this software without specific prior written permission.
     25        1.1  jdolecek  *
     26        1.1  jdolecek  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27        1.1  jdolecek  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28        1.1  jdolecek  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29        1.1  jdolecek  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30        1.1  jdolecek  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31        1.1  jdolecek  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32        1.1  jdolecek  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33        1.1  jdolecek  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34        1.1  jdolecek  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35        1.1  jdolecek  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36        1.1  jdolecek  * POSSIBILITY OF SUCH DAMAGE.
     37        1.1  jdolecek  */
     38        1.1  jdolecek 
     39        1.1  jdolecek /*-
     40        1.1  jdolecek  * Copyright (c) 1991 The Regents of the University of California.
     41        1.1  jdolecek  * All rights reserved.
     42        1.1  jdolecek  *
     43        1.1  jdolecek  * Redistribution and use in source and binary forms, with or without
     44        1.1  jdolecek  * modification, are permitted provided that the following conditions
     45        1.1  jdolecek  * are met:
     46        1.1  jdolecek  * 1. Redistributions of source code must retain the above copyright
     47        1.1  jdolecek  *    notice, this list of conditions and the following disclaimer.
     48        1.1  jdolecek  * 2. Redistributions in binary form must reproduce the above copyright
     49        1.1  jdolecek  *    notice, this list of conditions and the following disclaimer in the
     50        1.1  jdolecek  *    documentation and/or other materials provided with the distribution.
     51       1.10       agc  * 3. Neither the name of the University nor the names of its contributors
     52        1.1  jdolecek  *    may be used to endorse or promote products derived from this software
     53        1.1  jdolecek  *    without specific prior written permission.
     54        1.1  jdolecek  *
     55        1.1  jdolecek  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     56        1.1  jdolecek  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     57        1.1  jdolecek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     58        1.1  jdolecek  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     59        1.1  jdolecek  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     60        1.1  jdolecek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     61        1.1  jdolecek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     62        1.1  jdolecek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     63        1.1  jdolecek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     64        1.1  jdolecek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     65        1.1  jdolecek  * SUCH DAMAGE.
     66        1.1  jdolecek  *
     67        1.1  jdolecek  *	@(#)com.c	7.5 (Berkeley) 5/16/91
     68        1.1  jdolecek  */
     69        1.1  jdolecek 
     70        1.1  jdolecek /*
     71        1.1  jdolecek  * This driver attaches serial port boards and internal modems.
     72        1.1  jdolecek  */
     73        1.5     lukem 
     74        1.5     lukem #include <sys/cdefs.h>
     75  1.17.28.1    bouyer __KERNEL_RCSID(0, "$NetBSD: com_mca.c,v 1.17.28.1 2007/10/25 22:38:36 bouyer Exp $");
     76        1.1  jdolecek 
     77        1.1  jdolecek #include <sys/param.h>
     78        1.1  jdolecek #include <sys/systm.h>
     79        1.1  jdolecek #include <sys/ioctl.h>
     80        1.1  jdolecek #include <sys/select.h>
     81        1.1  jdolecek #include <sys/tty.h>
     82        1.1  jdolecek #include <sys/proc.h>
     83        1.1  jdolecek #include <sys/user.h>
     84        1.1  jdolecek #include <sys/file.h>
     85        1.1  jdolecek #include <sys/uio.h>
     86        1.1  jdolecek #include <sys/kernel.h>
     87        1.1  jdolecek #include <sys/syslog.h>
     88        1.1  jdolecek #include <sys/device.h>
     89        1.1  jdolecek 
     90  1.17.28.1    bouyer #include <sys/intr.h>
     91  1.17.28.1    bouyer #include <sys/bus.h>
     92        1.1  jdolecek 
     93        1.1  jdolecek #include <dev/ic/comreg.h>
     94        1.1  jdolecek #include <dev/ic/comvar.h>
     95        1.1  jdolecek 
     96        1.1  jdolecek #include <dev/mca/mcavar.h>
     97        1.1  jdolecek #include <dev/mca/mcadevs.h>
     98        1.1  jdolecek 
     99        1.1  jdolecek struct com_mca_softc {
    100        1.1  jdolecek 	struct	com_softc sc_com;	/* real "com" softc */
    101        1.1  jdolecek 
    102        1.1  jdolecek 	/* MCA-specific goo. */
    103        1.1  jdolecek 	void	*sc_ih;			/* interrupt handler */
    104        1.1  jdolecek };
    105        1.1  jdolecek 
    106       1.11     perry int com_mca_probe(struct device *, struct cfdata *, void *);
    107       1.11     perry void com_mca_attach(struct device *, struct device *, void *);
    108       1.11     perry 
    109       1.11     perry static int ibm_modem_getcfg(struct mca_attach_args *, int *, int *);
    110       1.11     perry static int neocom1_getcfg(struct mca_attach_args *, int *, int *);
    111       1.11     perry static int ibm_mpcom_getcfg(struct mca_attach_args *, int *, int *);
    112        1.1  jdolecek 
    113        1.8   thorpej CFATTACH_DECL(com_mca, sizeof(struct com_mca_softc),
    114        1.9   thorpej     com_mca_probe, com_mca_attach, NULL, NULL);
    115        1.1  jdolecek 
    116        1.1  jdolecek static const struct com_mca_product {
    117        1.1  jdolecek 	u_int32_t	cp_prodid;	/* MCA product ID */
    118        1.1  jdolecek 	const char	*cp_name;	/* device name */
    119       1.11     perry 	int (*cp_getcfg)(struct mca_attach_args *, int *iobase, int *irq);
    120        1.1  jdolecek 					/* get device i/o base and irq */
    121        1.1  jdolecek } com_mca_products[] = {
    122        1.1  jdolecek 	{ MCA_PRODUCT_IBM_MOD,	"IBM Internal Modem",	ibm_modem_getcfg },
    123        1.3  jdolecek 	{ MCA_PRODUCT_NEOCOM1,	"NeoTecH Single RS-232 Async. Adapter, SM110",
    124        1.3  jdolecek 		neocom1_getcfg },
    125        1.4  jdolecek 	{ MCA_PRODUCT_IBM_MPCOM,"IBM Multi-Protocol Communications Adapter",
    126        1.4  jdolecek 		ibm_mpcom_getcfg },
    127        1.1  jdolecek 	{ 0,			NULL,			NULL },
    128        1.1  jdolecek };
    129        1.1  jdolecek 
    130       1.11     perry static const struct com_mca_product *com_mca_lookup(int);
    131        1.1  jdolecek 
    132        1.1  jdolecek static const struct com_mca_product *
    133        1.1  jdolecek com_mca_lookup(ma_id)
    134        1.1  jdolecek 	int ma_id;
    135        1.1  jdolecek {
    136        1.1  jdolecek 	const struct com_mca_product *cpp;
    137        1.1  jdolecek 
    138        1.1  jdolecek 	for (cpp = com_mca_products; cpp->cp_name != NULL; cpp++)
    139        1.1  jdolecek 		if (cpp->cp_prodid == ma_id)
    140        1.1  jdolecek 			return (cpp);
    141        1.1  jdolecek 
    142        1.1  jdolecek 	return (NULL);
    143        1.1  jdolecek }
    144        1.1  jdolecek 
    145        1.1  jdolecek int
    146       1.17  christos com_mca_probe(struct device *parent, struct cfdata *match,
    147       1.16  christos     void *aux)
    148        1.1  jdolecek {
    149        1.1  jdolecek 	struct mca_attach_args *ma = aux;
    150        1.1  jdolecek 
    151        1.1  jdolecek 	if (com_mca_lookup(ma->ma_id))
    152        1.1  jdolecek 		return (1);
    153        1.1  jdolecek 
    154        1.1  jdolecek 	return (0);
    155        1.1  jdolecek }
    156        1.1  jdolecek 
    157        1.1  jdolecek void
    158       1.17  christos com_mca_attach(struct device *parent, struct device *self,
    159       1.16  christos     void *aux)
    160        1.1  jdolecek {
    161       1.14   thorpej 	struct com_mca_softc *isc = device_private(self);
    162        1.1  jdolecek 	struct com_softc *sc = &isc->sc_com;
    163        1.1  jdolecek 	int iobase, irq;
    164        1.1  jdolecek 	struct mca_attach_args *ma = aux;
    165        1.1  jdolecek 	const struct com_mca_product *cpp;
    166       1.15   gdamore 	bus_space_handle_t ioh;
    167        1.1  jdolecek 
    168        1.1  jdolecek 	cpp = com_mca_lookup(ma->ma_id);
    169        1.1  jdolecek 
    170        1.1  jdolecek 	/* get iobase and irq */
    171        1.4  jdolecek 	if ((*cpp->cp_getcfg)(ma, &iobase, &irq))
    172        1.1  jdolecek 		return;
    173        1.1  jdolecek 
    174       1.15   gdamore 	if (bus_space_map(ma->ma_iot, iobase, COM_NPORTS, 0, &ioh)) {
    175        1.1  jdolecek 		printf(": can't map i/o space\n");
    176        1.1  jdolecek 		return;
    177        1.1  jdolecek 	}
    178        1.1  jdolecek 
    179       1.15   gdamore 	COM_INIT_REGS(sc->sc_regs, ma->ma_iot, ioh, iobase);
    180        1.1  jdolecek 	sc->sc_frequency = COM_FREQ;
    181        1.1  jdolecek 
    182        1.3  jdolecek 	printf(" slot %d i/o %#x-%#x irq %d", ma->ma_slot + 1,
    183        1.3  jdolecek 		iobase, iobase + COM_NPORTS - 1, irq);
    184        1.3  jdolecek 
    185        1.1  jdolecek 	com_attach_subr(sc);
    186        1.1  jdolecek 
    187        1.3  jdolecek 	printf("%s: %s\n", sc->sc_dev.dv_xname, cpp->cp_name);
    188        1.3  jdolecek 
    189        1.1  jdolecek 	isc->sc_ih = mca_intr_establish(ma->ma_mc, irq, IPL_SERIAL,
    190        1.1  jdolecek 			comintr, sc);
    191        1.1  jdolecek 	if (isc->sc_ih == NULL) {
    192        1.1  jdolecek                 printf("%s: couldn't establish interrupt handler\n",
    193        1.1  jdolecek                     sc->sc_dev.dv_xname);
    194        1.1  jdolecek                 return;
    195        1.1  jdolecek         }
    196        1.1  jdolecek 
    197        1.1  jdolecek 	/*
    198        1.1  jdolecek 	 * Shutdown hook for buggy BIOSs that don't recognize the UART
    199        1.1  jdolecek 	 * without a disabled FIFO.
    200        1.1  jdolecek 	 * XXX is this necessary on MCA ? --- jdolecek
    201        1.1  jdolecek 	 */
    202       1.15   gdamore 	if (shutdownhook_establish(com_cleanup, sc) == NULL)
    203        1.1  jdolecek 		panic("com_mca_attach: could not establish shutdown hook");
    204        1.1  jdolecek }
    205        1.1  jdolecek 
    206        1.1  jdolecek /* map serial_X to iobase and irq */
    207        1.1  jdolecek static const struct {
    208        1.1  jdolecek 	int iobase;
    209        1.1  jdolecek 	int irq;
    210        1.1  jdolecek } MCA_SERIAL[] = {
    211        1.1  jdolecek 	{ 0x03f8,	4 },	/* SERIAL_1 */
    212        1.1  jdolecek 	{ 0x02f8,	3 },	/* SERIAL_2 */
    213        1.1  jdolecek 	{ 0x3220,	3 },	/* SERIAL_3 */
    214        1.1  jdolecek 	{ 0x3228,	3 },	/* SERIAL_4 */
    215        1.1  jdolecek 	{ 0x4220,	3 },	/* SERIAL_5 */
    216        1.1  jdolecek 	{ 0x4228,	3 },	/* SERIAL_6 */
    217        1.1  jdolecek 	{ 0x5220,	3 },	/* SERIAL_7 */
    218        1.1  jdolecek 	{ 0x5228,	3 },	/* SERIAL_8 */
    219        1.1  jdolecek };
    220        1.1  jdolecek 
    221        1.1  jdolecek /*
    222        1.1  jdolecek  * Get config for IBM Internal Modem (ID 0xEDFF). This beast doesn't
    223        1.1  jdolecek  * seem to support even AT commands, it's good as example for adding
    224        1.1  jdolecek  * other stuff though.
    225        1.1  jdolecek  */
    226        1.1  jdolecek static int
    227        1.1  jdolecek ibm_modem_getcfg(ma, iobasep, irqp)
    228        1.1  jdolecek 	struct mca_attach_args *ma;
    229        1.1  jdolecek 	int *iobasep, *irqp;
    230        1.1  jdolecek {
    231        1.1  jdolecek 	int pos2;
    232        1.1  jdolecek 	int snum;
    233        1.1  jdolecek 
    234        1.1  jdolecek 	pos2 = mca_conf_read(ma->ma_mc, ma->ma_slot, 2);
    235        1.1  jdolecek 
    236        1.1  jdolecek 	/*
    237        1.1  jdolecek 	 * POS register 2: (adf pos0)
    238        1.1  jdolecek 	 * 7 6 5 4 3 2 1 0
    239        1.1  jdolecek 	 *         \__/  \__ enable: 0=adapter disabled, 1=adapter enabled
    240       1.12     perry 	 *            \_____ Serial Configuration: XX=SERIAL_XX
    241       1.12     perry 	 */
    242       1.12     perry 
    243        1.1  jdolecek 	snum = (pos2 & 0x0e) >> 1;
    244        1.1  jdolecek 
    245        1.1  jdolecek 	*iobasep = MCA_SERIAL[snum].iobase;
    246        1.1  jdolecek 	*irqp = MCA_SERIAL[snum].irq;
    247        1.3  jdolecek 
    248        1.3  jdolecek 	return (0);
    249        1.3  jdolecek }
    250        1.3  jdolecek 
    251        1.3  jdolecek /*
    252        1.3  jdolecek  * Get configuration for NeoTecH Single RS-232 Async. Adapter, SM110.
    253        1.3  jdolecek  */
    254        1.3  jdolecek static int
    255        1.3  jdolecek neocom1_getcfg(ma, iobasep, irqp)
    256        1.3  jdolecek 	struct mca_attach_args *ma;
    257        1.3  jdolecek 	int *iobasep, *irqp;
    258        1.3  jdolecek {
    259        1.3  jdolecek 	int pos2, pos3, pos4;
    260        1.3  jdolecek 	static const int neotech_irq[] = { 12, 9, 4, 3 };
    261        1.3  jdolecek 
    262        1.3  jdolecek 	pos2 = mca_conf_read(ma->ma_mc, ma->ma_slot, 2);
    263        1.3  jdolecek 	pos3 = mca_conf_read(ma->ma_mc, ma->ma_slot, 3);
    264        1.3  jdolecek 	pos4 = mca_conf_read(ma->ma_mc, ma->ma_slot, 4);
    265        1.3  jdolecek 
    266        1.3  jdolecek 	/*
    267        1.3  jdolecek 	 * POS register 2: (adf pos0)
    268        1.3  jdolecek 	 * 7 6 5 4 3 2 1 0
    269        1.3  jdolecek 	 *     1     \_/ \__ enable: 0=adapter disabled, 1=adapter enabled
    270        1.3  jdolecek 	 *             \____ IRQ: 11=3 10=4 01=9 00=12
    271        1.3  jdolecek 	 *
    272        1.3  jdolecek 	 * POS register 3: (adf pos1)
    273        1.3  jdolecek 	 * 7 6 5 4 3 2 1 0
    274        1.3  jdolecek 	 * \______/
    275        1.3  jdolecek 	 *        \_________ I/O Address: bits 7-3
    276        1.3  jdolecek 	 *
    277        1.3  jdolecek 	 * POS register 4: (adf pos2)
    278        1.3  jdolecek 	 * 7 6 5 4 3 2 1 0
    279        1.3  jdolecek 	 * \_____________/
    280        1.3  jdolecek 	 *               \__ I/O Address: bits 15-8
    281       1.12     perry 	 */
    282       1.12     perry 
    283        1.3  jdolecek 	*iobasep = (pos4 << 8) | (pos3 & 0xf8);
    284        1.3  jdolecek 	*irqp = neotech_irq[(pos2 & 0x06) >> 1];
    285        1.4  jdolecek 
    286        1.4  jdolecek 	return (0);
    287        1.4  jdolecek }
    288        1.4  jdolecek 
    289        1.4  jdolecek /*
    290        1.4  jdolecek  * Get configuration for IBM Multi-Protocol Communications Adapter.
    291        1.4  jdolecek  * We only support SERIAL mode, bail out if set to SDLC or BISYNC.
    292        1.4  jdolecek  */
    293        1.4  jdolecek static int
    294        1.4  jdolecek ibm_mpcom_getcfg(ma, iobasep, irqp)
    295        1.4  jdolecek 	struct mca_attach_args *ma;
    296        1.4  jdolecek 	int *iobasep, *irqp;
    297        1.4  jdolecek {
    298        1.4  jdolecek 	int snum, pos2;
    299        1.4  jdolecek 
    300        1.4  jdolecek 	pos2 = mca_conf_read(ma->ma_mc, ma->ma_slot, 2);
    301        1.4  jdolecek 
    302        1.4  jdolecek 	/*
    303        1.4  jdolecek 	 * For SERIAL mode, bit 4 has to be 0.
    304        1.4  jdolecek 	 *
    305        1.4  jdolecek 	 * POS register 2: (adf pos0)
    306        1.4  jdolecek 	 * 7 6 5 4 3 2 1 0
    307        1.4  jdolecek 	 *       0 \__/  \__ enable: 0=adapter disabled, 1=adapter enabled
    308       1.12     perry 	 *            \_____ Serial Configuration: XX=SERIAL_XX
    309       1.12     perry 	 */
    310       1.12     perry 
    311        1.4  jdolecek 	if (pos2 & 0x10) {
    312        1.4  jdolecek 		printf(": not set to SERIAL mode, ignored\n");
    313        1.4  jdolecek 		return (1);
    314        1.4  jdolecek 	}
    315        1.4  jdolecek 
    316        1.4  jdolecek 	snum = (pos2 & 0x0e) >> 1;
    317        1.4  jdolecek 
    318        1.4  jdolecek 	*iobasep = MCA_SERIAL[snum].iobase;
    319        1.4  jdolecek 	*irqp = MCA_SERIAL[snum].irq;
    320        1.1  jdolecek 
    321        1.1  jdolecek 	return (0);
    322        1.1  jdolecek }
    323