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