1 /*- 2 * Copyright (c) 1993, 1994 Charles Hannum. 3 * Copyright (c) 1991 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * William Jolitz. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the University of 20 * California, Berkeley and its contributors. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 38 * $Id: isa.c,v 1.55 1994/05/05 05:36:35 cgd Exp $ 39 */ 40 41 /* 42 * Code to manage AT bus 43 */ 44 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/kernel.h> 48 #include <sys/conf.h> 49 #include <sys/malloc.h> 50 #include <sys/device.h> 51 52 #include <machine/pio.h> 53 #include <machine/cpufunc.h> 54 55 #include <i386/isa/isareg.h> 56 #include <i386/isa/isa_device.h> 57 #include <i386/isa/isavar.h> 58 #include <i386/isa/ic/i8042.h> 59 60 /* sorry, has to be here, no place else really suitable */ 61 #include <machine/pc/display.h> 62 u_short *Crtat = (u_short *)MONO_BUF; 63 64 /* 65 * Configure all ISA devices 66 * 67 * XXX This code is a hack. It wants to be new config, but can't be until the 68 * interrupt system is redone. For now, we do some gross hacks to make it look 69 * 99% like new config. 70 */ 71 static char *msgs[3] = { "", " not configured\n", " unsupported\n" }; 72 73 struct cfdata * 74 config_search(fn, parent, aux) 75 cfmatch_t fn; 76 struct device *parent; 77 void *aux; 78 { 79 struct cfdata *cf = 0; 80 struct device *dv = 0; 81 size_t devsize; 82 struct cfdriver *cd; 83 struct isa_device *id, 84 *idp = parent ? (void *)parent->dv_cfdata->cf_loc : 0; 85 86 for (id = isa_devtab; id->id_driver; id++) { 87 if (id->id_state == FSTATE_FOUND) 88 continue; 89 if (id->id_parent != idp) 90 continue; 91 cd = id->id_driver; 92 if (id->id_unit < cd->cd_ndevs) { 93 if (cd->cd_devs[id->id_unit] != 0) 94 continue; 95 } else { 96 int old = cd->cd_ndevs, new; 97 void **nsp; 98 99 if (old == 0) { 100 nsp = malloc(MINALLOCSIZE, M_DEVBUF, M_NOWAIT); 101 if (!nsp) 102 panic("config_search: creating dev array"); 103 bzero(nsp, MINALLOCSIZE); 104 cd->cd_ndevs = MINALLOCSIZE / sizeof(void *); 105 } else { 106 new = old; 107 do { 108 new *= 2; 109 } while (new <= id->id_unit); 110 cd->cd_ndevs = new; 111 nsp = malloc(new * sizeof(void *), M_DEVBUF, 112 M_NOWAIT); 113 if (!nsp) 114 panic("config_search: expanding dev array"); 115 bzero(nsp, new * sizeof(void *)); 116 bcopy(cd->cd_devs, nsp, old * sizeof(void *)); 117 free(cd->cd_devs, M_DEVBUF); 118 } 119 cd->cd_devs = nsp; 120 } 121 if (!cf) { 122 cf = malloc(sizeof(struct cfdata), M_DEVBUF, M_NOWAIT); 123 if (!cf) 124 panic("config_search: creating cfdata"); 125 } 126 cf->cf_driver = cd; 127 cf->cf_unit = id->id_unit; 128 cf->cf_fstate = 0; 129 cf->cf_loc = (void *)id; 130 cf->cf_flags = id->id_flags; 131 cf->cf_parents = 0; 132 cf->cf_ivstubs = 0; 133 if (dv && devsize != cd->cd_devsize) { 134 free(dv, M_DEVBUF); 135 dv = 0; 136 } 137 if (!dv) { 138 devsize = cd->cd_devsize; 139 dv = malloc(devsize, M_DEVBUF, M_NOWAIT); 140 if (!dv) 141 panic("config_search: creating softc"); 142 } 143 bzero(dv, cd->cd_devsize); 144 dv->dv_class = cd->cd_class; 145 dv->dv_cfdata = cf; 146 dv->dv_unit = id->id_unit; 147 sprintf(dv->dv_xname, "%s%d", cd->cd_name, id->id_unit); 148 dv->dv_parent = parent; 149 cd->cd_devs[id->id_unit] = dv; 150 if (fn) { 151 if ((*fn)(parent, dv, aux)) 152 return cf; 153 } else { 154 if ((*cd->cd_match)(parent, dv, aux)) 155 return cf; 156 } 157 cd->cd_devs[id->id_unit] = 0; 158 } 159 if (cf) 160 free(cf, M_DEVBUF); 161 if (dv) 162 free(dv, M_DEVBUF); 163 return 0; 164 } 165 166 void 167 config_attach(parent, cf, aux, print) 168 struct device *parent; 169 struct cfdata *cf; 170 void *aux; 171 cfprint_t print; 172 { 173 struct isa_device *id = (void *)cf->cf_loc; 174 struct cfdriver *cd = cf->cf_driver; 175 struct device *dv = cd->cd_devs[id->id_unit]; 176 177 cf->cf_fstate = id->id_state = FSTATE_FOUND; 178 printf("%s at %s", dv->dv_xname, parent ? parent->dv_xname : "isa0"); 179 if (print) 180 (void) (*print)(aux, (char *)0); 181 (*cd->cd_attach)(parent, dv, aux); 182 } 183 184 int 185 config_found(parent, aux, print) 186 struct device *parent; 187 void *aux; 188 cfprint_t print; 189 { 190 struct cfdata *cf; 191 192 if ((cf = config_search((cfmatch_t)NULL, parent, aux)) != NULL) { 193 config_attach(parent, cf, aux, print); 194 return 1; 195 } 196 if (print) 197 printf(msgs[(*print)(aux, parent->dv_xname)]); 198 return 0; 199 } 200 201 int 202 isaprint(aux, isa) 203 void *aux; 204 char *isa; 205 { 206 struct isa_attach_args *ia = aux; 207 208 if (ia->ia_iosize) 209 printf(" port 0x%x", ia->ia_iobase); 210 if (ia->ia_iosize > 1) 211 printf("-0x%x", ia->ia_iobase + ia->ia_iosize - 1); 212 if (ia->ia_msize) 213 printf(" iomem 0x%x", ia->ia_maddr - atdevbase + 0xa0000); 214 if (ia->ia_msize > 1) 215 printf("-0x%x", 216 ia->ia_maddr - atdevbase + 0xa0000 + ia->ia_msize - 1); 217 if (ia->ia_irq) 218 printf(" irq %d", ffs(ia->ia_irq) - 1); 219 if (ia->ia_drq != (u_short)-1) 220 printf(" drq %d", ia->ia_drq); 221 /* XXXX print flags */ 222 return QUIET; 223 } 224 225 int 226 isasubmatch(parent, self, aux) 227 struct device *parent, *self; 228 void *aux; 229 { 230 struct isa_device *id = (void *)self->dv_cfdata->cf_loc; 231 struct isa_attach_args ia; 232 233 ia.ia_iobase = id->id_iobase; 234 ia.ia_iosize = 0x666; 235 ia.ia_irq = id->id_irq; 236 ia.ia_drq = id->id_drq; 237 ia.ia_maddr = id->id_maddr - 0xa0000 + atdevbase; 238 ia.ia_msize = id->id_msize; 239 240 if (!(*id->id_driver->cd_match)(parent, self, &ia)) { 241 /* 242 * If we don't do this, isa_configure() will repeatedly try to 243 * probe devices that weren't found. But we need to be careful 244 * to do it only for the ISA bus, or we would cause things like 245 * `com0 at ast? slave ?' to not probe on the second ast. 246 */ 247 if (!parent) 248 id->id_state = FSTATE_FOUND; 249 250 return 0; 251 } 252 253 config_attach(parent, self->dv_cfdata, &ia, isaprint); 254 255 return 1; 256 } 257 258 void 259 isa_configure() 260 { 261 262 startrtclock(); 263 264 while (config_search(isasubmatch, NULL, NULL)); 265 266 printf("biomask %x netmask %x ttymask %x\n", 267 (u_short)imask[IPL_BIO], (u_short)imask[IPL_NET], 268 (u_short)imask[IPL_TTY]); 269 270 spl0(); 271 } 272