1 /* $OpenBSD: ast.c,v 1.4 1996/03/08 16:42:48 niklas Exp $ */ 2 /* $NetBSD: ast.c,v 1.18 1995/06/26 04:08:04 cgd Exp $ */ 3 4 /* 5 * Copyright (c) 1995 Charles Hannum. All rights reserved. 6 * 7 * This code is derived from public-domain software written by 8 * Roland McGrath. 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 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by Charles Hannum. 21 * 4. The name of the author may not be used to endorse or promote products 22 * derived from this software without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 #include <sys/param.h> 37 #include <sys/device.h> 38 39 #include <machine/pio.h> 40 41 #include <dev/isa/isavar.h> 42 43 struct ast_softc { 44 struct device sc_dev; 45 void *sc_ih; 46 47 int sc_iobase; 48 int sc_alive; /* mask of slave units attached */ 49 void *sc_slaves[4]; /* com device unit numbers */ 50 }; 51 52 int astprobe(); 53 void astattach(); 54 int astintr __P((void *)); 55 56 struct cfdriver astcd = { 57 NULL, "ast", astprobe, astattach, DV_TTY, sizeof(struct ast_softc) 58 }; 59 60 int 61 astprobe(parent, self, aux) 62 struct device *parent, *self; 63 void *aux; 64 { 65 struct isa_attach_args *ia = aux; 66 67 /* 68 * Do the normal com probe for the first UART and assume 69 * its presence means there is a multiport board there. 70 * XXX Needs more robustness. 71 */ 72 ia->ia_iosize = 4 * 8; 73 return (comprobe1(ia->ia_iobase)); 74 } 75 76 struct ast_attach_args { 77 int aa_slave; 78 }; 79 80 int 81 astsubmatch(parent, match, aux) 82 struct device *parent; 83 void *match, *aux; 84 { 85 struct ast_softc *sc = (void *)parent; 86 struct cfdata *cf = match; 87 struct isa_attach_args *ia = aux; 88 struct ast_attach_args *aa = ia->ia_aux; 89 90 if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != aa->aa_slave) 91 return (0); 92 return ((*cf->cf_driver->cd_match)(parent, match, ia)); 93 } 94 95 int 96 astprint(aux, ast) 97 void *aux; 98 char *ast; 99 { 100 struct isa_attach_args *ia = aux; 101 struct ast_attach_args *aa = ia->ia_aux; 102 103 printf(" slave %d", aa->aa_slave); 104 } 105 106 void 107 astattach(parent, self, aux) 108 struct device *parent, *self; 109 void *aux; 110 { 111 struct ast_softc *sc = (void *)self; 112 struct isa_attach_args *ia = aux; 113 struct ast_attach_args aa; 114 struct isa_attach_args isa; 115 int subunit; 116 117 sc->sc_iobase = ia->ia_iobase; 118 119 /* 120 * Enable the master interrupt. 121 */ 122 outb(sc->sc_iobase | 0x1f, 0x80); 123 124 printf("\n"); 125 126 isa.ia_aux = &aa; 127 for (aa.aa_slave = 0; aa.aa_slave < 4; aa.aa_slave++) { 128 struct cfdata *cf; 129 isa.ia_iobase = sc->sc_iobase + 8 * aa.aa_slave; 130 isa.ia_iosize = 0x666; 131 isa.ia_irq = IRQUNK; 132 isa.ia_drq = DRQUNK; 133 isa.ia_msize = 0; 134 if ((cf = config_search(astsubmatch, self, &isa)) != 0) { 135 subunit = cf->cf_unit; /* can change if unit == * */ 136 config_attach(self, cf, &isa, astprint); 137 sc->sc_slaves[aa.aa_slave] = 138 cf->cf_driver->cd_devs[subunit]; 139 sc->sc_alive |= 1 << aa.aa_slave; 140 } 141 } 142 143 sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_TTY, astintr, 144 sc, sc->sc_dev.dv_xname); 145 } 146 147 int 148 astintr(arg) 149 void *arg; 150 { 151 struct ast_softc *sc = arg; 152 int iobase = sc->sc_iobase; 153 int alive = sc->sc_alive; 154 int bits; 155 156 bits = ~inb(iobase | 0x1f) & alive; 157 if (bits == 0) 158 return (0); 159 160 for (;;) { 161 #define TRY(n) \ 162 if (bits & (1 << (n))) \ 163 comintr(sc->sc_slaves[n]); 164 TRY(0); 165 TRY(1); 166 TRY(2); 167 TRY(3); 168 #undef TRY 169 bits = ~inb(iobase | 0x1f) & alive; 170 if (bits == 0) 171 return (1); 172 } 173 } 174