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