1 /* $NetBSD: eisa.c,v 1.22 2000/03/30 12:45:28 augustss Exp $ */ 2 3 /* 4 * Copyright (c) 1995, 1996 Christopher G. Demetriou 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Christopher G. Demetriou 18 * for the NetBSD Project. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * EISA Bus device 36 * 37 * Makes sure an EISA bus is present, and finds and attaches devices 38 * living on it. 39 */ 40 41 #include "opt_eisaverbose.h" 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/device.h> 46 47 #include <machine/bus.h> 48 49 #include <dev/eisa/eisareg.h> 50 #include <dev/eisa/eisavar.h> 51 #include <dev/eisa/eisadevs.h> 52 53 int eisamatch __P((struct device *, struct cfdata *, void *)); 54 void eisaattach __P((struct device *, struct device *, void *)); 55 56 struct cfattach eisa_ca = { 57 sizeof(struct device), eisamatch, eisaattach 58 }; 59 60 int eisasubmatch __P((struct device *, struct cfdata *, void *)); 61 int eisaprint __P((void *, const char *)); 62 void eisa_devinfo __P((const char *, char *)); 63 64 int 65 eisamatch(parent, cf, aux) 66 struct device *parent; 67 struct cfdata *cf; 68 void *aux; 69 { 70 struct eisabus_attach_args *eba = aux; 71 72 if (strcmp(eba->eba_busname, cf->cf_driver->cd_name)) 73 return (0); 74 75 /* XXX check other indicators */ 76 77 return (1); 78 } 79 80 int 81 eisaprint(aux, pnp) 82 void *aux; 83 const char *pnp; 84 { 85 struct eisa_attach_args *ea = aux; 86 char devinfo[256]; 87 88 if (pnp) { 89 eisa_devinfo(ea->ea_idstring, devinfo); 90 printf("%s at %s", devinfo, pnp); 91 } 92 printf(" slot %d", ea->ea_slot); 93 return (UNCONF); 94 } 95 96 int 97 eisasubmatch(parent, cf, aux) 98 struct device *parent; 99 struct cfdata *cf; 100 void *aux; 101 { 102 struct eisa_attach_args *ea = aux; 103 104 if (cf->eisacf_slot != EISA_UNKNOWN_SLOT && 105 cf->eisacf_slot != ea->ea_slot) 106 return 0; 107 return ((*cf->cf_attach->ca_match)(parent, cf, aux)); 108 } 109 110 void 111 eisaattach(parent, self, aux) 112 struct device *parent, *self; 113 void *aux; 114 { 115 struct eisabus_attach_args *eba = aux; 116 bus_space_tag_t iot, memt; 117 bus_dma_tag_t dmat; 118 eisa_chipset_tag_t ec; 119 int slot, maxnslots; 120 121 eisa_attach_hook(parent, self, eba); 122 printf("\n"); 123 124 iot = eba->eba_iot; 125 memt = eba->eba_memt; 126 ec = eba->eba_ec; 127 dmat = eba->eba_dmat; 128 129 /* 130 * Search for and attach subdevices. 131 * 132 * Slot 0 is the "motherboard" slot, and the code attaching 133 * the EISA bus should have already attached an ISA bus there. 134 */ 135 maxnslots = eisa_maxslots(ec); 136 for (slot = 1; slot < maxnslots; slot++) { 137 struct eisa_attach_args ea; 138 u_int slotaddr; 139 bus_space_handle_t slotioh; 140 int i; 141 142 ea.ea_iot = iot; 143 ea.ea_memt = memt; 144 ea.ea_ec = ec; 145 ea.ea_dmat = dmat; 146 ea.ea_slot = slot; 147 slotaddr = EISA_SLOT_ADDR(slot); 148 149 /* 150 * Get a mapping for the whole slot-specific address 151 * space. If we can't, assume nothing's there but warn 152 * about it. 153 */ 154 if (bus_space_map(iot, slotaddr, EISA_SLOT_SIZE, 0, &slotioh)) { 155 printf("%s: can't map I/O space for slot %d\n", 156 self->dv_xname, slot); 157 continue; 158 } 159 160 /* Get the vendor ID bytes */ 161 for (i = 0; i < EISA_NVIDREGS; i++) 162 ea.ea_vid[i] = bus_space_read_1(iot, slotioh, 163 EISA_SLOTOFF_VID + i); 164 165 /* Check for device existence */ 166 if (EISA_VENDID_NODEV(ea.ea_vid)) { 167 #if 0 168 printf("no device at %s slot %d\n", self->dv_xname, 169 slot); 170 printf("\t(0x%x, 0x%x)\n", ea.ea_vid[0], 171 ea.ea_vid[1]); 172 #endif 173 bus_space_unmap(iot, slotioh, EISA_SLOT_SIZE); 174 continue; 175 } 176 177 /* And check that the firmware didn't biff something badly */ 178 if (EISA_VENDID_IDDELAY(ea.ea_vid)) { 179 printf("%s slot %d not configured by BIOS?\n", 180 self->dv_xname, slot); 181 bus_space_unmap(iot, slotioh, EISA_SLOT_SIZE); 182 continue; 183 } 184 185 /* Get the product ID bytes */ 186 for (i = 0; i < EISA_NPIDREGS; i++) 187 ea.ea_pid[i] = bus_space_read_1(iot, slotioh, 188 EISA_SLOTOFF_PID + i); 189 190 /* Create the ID string from the vendor and product IDs */ 191 ea.ea_idstring[0] = EISA_VENDID_0(ea.ea_vid); 192 ea.ea_idstring[1] = EISA_VENDID_1(ea.ea_vid); 193 ea.ea_idstring[2] = EISA_VENDID_2(ea.ea_vid); 194 ea.ea_idstring[3] = EISA_PRODID_0(ea.ea_pid); 195 ea.ea_idstring[4] = EISA_PRODID_1(ea.ea_pid); 196 ea.ea_idstring[5] = EISA_PRODID_2(ea.ea_pid); 197 ea.ea_idstring[6] = EISA_PRODID_3(ea.ea_pid); 198 ea.ea_idstring[7] = '\0'; /* sanity */ 199 200 /* We no longer need the I/O handle; free it. */ 201 bus_space_unmap(iot, slotioh, EISA_SLOT_SIZE); 202 203 /* Attach matching device. */ 204 config_found_sm(self, &ea, eisaprint, eisasubmatch); 205 } 206 } 207 208 #ifdef EISAVERBOSE 209 /* 210 * Descriptions of of known vendors and devices ("products"). 211 */ 212 struct eisa_knowndev { 213 int flags; 214 const char *id, *name; 215 }; 216 #define EISA_KNOWNDEV_NOPROD 0x01 /* match on vendor only */ 217 218 #include <dev/eisa/eisadevs_data.h> 219 #endif /* EISAVERBOSE */ 220 221 void 222 eisa_devinfo(id, cp) 223 const char *id; 224 char *cp; 225 { 226 const char *name; 227 int onlyvendor; 228 #ifdef EISAVERBOSE 229 struct eisa_knowndev *edp; 230 int match; 231 const char *unmatched = "unknown "; 232 #else 233 const char *unmatched = ""; 234 #endif 235 236 onlyvendor = 0; 237 name = NULL; 238 239 #ifdef EISAVERBOSE 240 /* find the device in the table, if possible. */ 241 edp = eisa_knowndevs; 242 while (edp->id != NULL) { 243 /* check this entry for a match */ 244 if ((edp->flags & EISA_KNOWNDEV_NOPROD) != 0) 245 match = !strncmp(edp->id, id, 3); 246 else 247 match = !strcmp(edp->id, id); 248 if (match) { 249 name = edp->name; 250 onlyvendor = (edp->flags & EISA_KNOWNDEV_NOPROD) != 0; 251 break; 252 } 253 edp++; 254 } 255 #endif 256 257 if (name == NULL) 258 cp += sprintf(cp, "%sdevice %s", unmatched, id); 259 else if (onlyvendor) /* never if not EISAVERBOSE */ 260 cp += sprintf(cp, "unknown %s device %s", name, id); 261 else 262 cp += sprintf(cp, "%s", name); 263 } 264