1 /* $NetBSD: com_mca.c,v 1.21 2008/04/28 20:23:53 martin 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.21 2008/04/28 20:23:53 martin 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/user.h> 77 #include <sys/file.h> 78 #include <sys/uio.h> 79 #include <sys/kernel.h> 80 #include <sys/syslog.h> 81 #include <sys/device.h> 82 83 #include <sys/intr.h> 84 #include <sys/bus.h> 85 86 #include <dev/ic/comreg.h> 87 #include <dev/ic/comvar.h> 88 89 #include <dev/mca/mcavar.h> 90 #include <dev/mca/mcadevs.h> 91 92 struct com_mca_softc { 93 struct com_softc sc_com; /* real "com" softc */ 94 95 /* MCA-specific goo. */ 96 void *sc_ih; /* interrupt handler */ 97 }; 98 99 int com_mca_probe(device_t, cfdata_t , void *); 100 void com_mca_attach(device_t, device_t, void *); 101 102 static int ibm_modem_getcfg(struct mca_attach_args *, int *, int *); 103 static int neocom1_getcfg(struct mca_attach_args *, int *, int *); 104 static int ibm_mpcom_getcfg(struct mca_attach_args *, int *, int *); 105 106 CFATTACH_DECL_NEW(com_mca, sizeof(struct com_mca_softc), 107 com_mca_probe, com_mca_attach, NULL, NULL); 108 109 static const struct com_mca_product { 110 u_int32_t cp_prodid; /* MCA product ID */ 111 const char *cp_name; /* device name */ 112 int (*cp_getcfg)(struct mca_attach_args *, int *iobase, int *irq); 113 /* get device i/o base and irq */ 114 } com_mca_products[] = { 115 { MCA_PRODUCT_IBM_MOD, "IBM Internal Modem", ibm_modem_getcfg }, 116 { MCA_PRODUCT_NEOCOM1, "NeoTecH Single RS-232 Async. Adapter, SM110", 117 neocom1_getcfg }, 118 { MCA_PRODUCT_IBM_MPCOM,"IBM Multi-Protocol Communications Adapter", 119 ibm_mpcom_getcfg }, 120 { 0, NULL, NULL }, 121 }; 122 123 static const struct com_mca_product *com_mca_lookup(int); 124 125 static const struct com_mca_product * 126 com_mca_lookup(int ma_id) 127 { 128 const struct com_mca_product *cpp; 129 130 for (cpp = com_mca_products; cpp->cp_name != NULL; cpp++) 131 if (cpp->cp_prodid == ma_id) 132 return (cpp); 133 134 return (NULL); 135 } 136 137 int 138 com_mca_probe(device_t parent, cfdata_t match, void *aux) 139 { 140 struct mca_attach_args *ma = aux; 141 142 if (com_mca_lookup(ma->ma_id)) 143 return (1); 144 145 return (0); 146 } 147 148 void 149 com_mca_attach(device_t parent, device_t self, void *aux) 150 { 151 struct com_mca_softc *isc = device_private(self); 152 struct com_softc *sc = &isc->sc_com; 153 int iobase, irq; 154 struct mca_attach_args *ma = aux; 155 const struct com_mca_product *cpp; 156 bus_space_handle_t ioh; 157 158 sc->sc_dev = self; 159 cpp = com_mca_lookup(ma->ma_id); 160 161 /* get iobase and irq */ 162 if ((*cpp->cp_getcfg)(ma, &iobase, &irq)) 163 return; 164 165 if (bus_space_map(ma->ma_iot, iobase, COM_NPORTS, 0, &ioh)) { 166 aprint_error(": can't map i/o space\n"); 167 return; 168 } 169 170 COM_INIT_REGS(sc->sc_regs, ma->ma_iot, ioh, iobase); 171 sc->sc_frequency = COM_FREQ; 172 173 aprint_normal(" slot %d i/o %#x-%#x irq %d", ma->ma_slot + 1, 174 iobase, iobase + COM_NPORTS - 1, irq); 175 176 com_attach_subr(sc); 177 178 aprint_normal_dev(self, "%s\n", cpp->cp_name); 179 180 isc->sc_ih = mca_intr_establish(ma->ma_mc, irq, IPL_SERIAL, 181 comintr, sc); 182 if (isc->sc_ih == NULL) { 183 aprint_error_dev(self, 184 "couldn't establish interrupt handler\n"); 185 return; 186 } 187 188 /* 189 * com_cleanup: shutdown hook for buggy BIOSs that don't 190 * recognize the UART without a disabled FIFO. 191 * XXX is this necessary on MCA ? --- jdolecek 192 */ 193 if (!pmf_device_register1(self, com_suspend, com_resume, com_cleanup)) 194 aprint_error_dev(self, "could not establish shutdown hook\n"); 195 } 196 197 /* map serial_X to iobase and irq */ 198 static const struct { 199 int iobase; 200 int irq; 201 } MCA_SERIAL[] = { 202 { 0x03f8, 4 }, /* SERIAL_1 */ 203 { 0x02f8, 3 }, /* SERIAL_2 */ 204 { 0x3220, 3 }, /* SERIAL_3 */ 205 { 0x3228, 3 }, /* SERIAL_4 */ 206 { 0x4220, 3 }, /* SERIAL_5 */ 207 { 0x4228, 3 }, /* SERIAL_6 */ 208 { 0x5220, 3 }, /* SERIAL_7 */ 209 { 0x5228, 3 }, /* SERIAL_8 */ 210 }; 211 212 /* 213 * Get config for IBM Internal Modem (ID 0xEDFF). This beast doesn't 214 * seem to support even AT commands, it's good as example for adding 215 * other stuff though. 216 */ 217 static int 218 ibm_modem_getcfg(struct mca_attach_args *ma, int *iobasep, int *irqp) 219 { 220 int pos2; 221 int snum; 222 223 pos2 = mca_conf_read(ma->ma_mc, ma->ma_slot, 2); 224 225 /* 226 * POS register 2: (adf pos0) 227 * 7 6 5 4 3 2 1 0 228 * \__/ \__ enable: 0=adapter disabled, 1=adapter enabled 229 * \_____ Serial Configuration: XX=SERIAL_XX 230 */ 231 232 snum = (pos2 & 0x0e) >> 1; 233 234 *iobasep = MCA_SERIAL[snum].iobase; 235 *irqp = MCA_SERIAL[snum].irq; 236 237 return (0); 238 } 239 240 /* 241 * Get configuration for NeoTecH Single RS-232 Async. Adapter, SM110. 242 */ 243 static int 244 neocom1_getcfg(struct mca_attach_args *ma, int *iobasep, int *irqp) 245 { 246 int pos2, pos3, pos4; 247 static const int neotech_irq[] = { 12, 9, 4, 3 }; 248 249 pos2 = mca_conf_read(ma->ma_mc, ma->ma_slot, 2); 250 pos3 = mca_conf_read(ma->ma_mc, ma->ma_slot, 3); 251 pos4 = mca_conf_read(ma->ma_mc, ma->ma_slot, 4); 252 253 /* 254 * POS register 2: (adf pos0) 255 * 7 6 5 4 3 2 1 0 256 * 1 \_/ \__ enable: 0=adapter disabled, 1=adapter enabled 257 * \____ IRQ: 11=3 10=4 01=9 00=12 258 * 259 * POS register 3: (adf pos1) 260 * 7 6 5 4 3 2 1 0 261 * \______/ 262 * \_________ I/O Address: bits 7-3 263 * 264 * POS register 4: (adf pos2) 265 * 7 6 5 4 3 2 1 0 266 * \_____________/ 267 * \__ I/O Address: bits 15-8 268 */ 269 270 *iobasep = (pos4 << 8) | (pos3 & 0xf8); 271 *irqp = neotech_irq[(pos2 & 0x06) >> 1]; 272 273 return (0); 274 } 275 276 /* 277 * Get configuration for IBM Multi-Protocol Communications Adapter. 278 * We only support SERIAL mode, bail out if set to SDLC or BISYNC. 279 */ 280 static int 281 ibm_mpcom_getcfg(struct mca_attach_args *ma, int *iobasep, int *irqp) 282 { 283 int snum, pos2; 284 285 pos2 = mca_conf_read(ma->ma_mc, ma->ma_slot, 2); 286 287 /* 288 * For SERIAL mode, bit 4 has to be 0. 289 * 290 * POS register 2: (adf pos0) 291 * 7 6 5 4 3 2 1 0 292 * 0 \__/ \__ enable: 0=adapter disabled, 1=adapter enabled 293 * \_____ Serial Configuration: XX=SERIAL_XX 294 */ 295 296 if (pos2 & 0x10) { 297 aprint_error(": not set to SERIAL mode, ignored\n"); 298 return (1); 299 } 300 301 snum = (pos2 & 0x0e) >> 1; 302 303 *iobasep = MCA_SERIAL[snum].iobase; 304 *irqp = MCA_SERIAL[snum].irq; 305 306 return (0); 307 } 308