1 /* $OpenBSD: eisa.c,v 1.15 2022/04/06 18:59:28 naddy 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 const 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(struct device *parent, void *match, void *aux) 69 { 70 struct cfdata *cf = match; 71 struct eisabus_attach_args *eba = aux; 72 73 if (strcmp(eba->eba_busname, cf->cf_driver->cd_name)) 74 return (0); 75 76 /* XXX check other indicators */ 77 78 return (1); 79 } 80 81 int 82 eisaprint(void *aux, const char *pnp) 83 { 84 register struct eisa_attach_args *ea = aux; 85 char devinfo[256]; 86 87 if (pnp) { 88 eisa_devinfo(ea->ea_idstring, devinfo, sizeof devinfo); 89 printf("%s at %s", devinfo, pnp); 90 } 91 printf(" slot %d", ea->ea_slot); 92 return (UNCONF); 93 } 94 95 int 96 eisasubmatch(struct device *parent, void *match, void *aux) 97 { 98 struct cfdata *cf = match; 99 struct eisa_attach_args *ea = aux; 100 101 if (cf->eisacf_slot != EISA_UNKNOWN_SLOT && 102 cf->eisacf_slot != ea->ea_slot) 103 return 0; 104 return ((*cf->cf_attach->ca_match)(parent, match, aux)); 105 } 106 107 void 108 eisaattach(struct device *parent, struct device *self, void *aux) 109 { 110 struct eisabus_attach_args *eba = aux; 111 bus_space_tag_t iot, memt; 112 eisa_chipset_tag_t ec; 113 int slot, maxnslots; 114 115 eisa_attach_hook(parent, self, eba); 116 printf("\n"); 117 118 iot = eba->eba_iot; 119 memt = eba->eba_memt; 120 ec = eba->eba_ec; 121 122 /* 123 * Search for and attach subdevices. 124 * 125 * Slot 0 is the "motherboard" slot, and the code attaching 126 * the EISA bus should have already attached an ISA bus there. 127 */ 128 maxnslots = eisa_maxslots(ec); 129 for (slot = 1; slot < maxnslots; slot++) { 130 struct eisa_attach_args ea; 131 u_int slotaddr; 132 bus_space_handle_t slotioh; 133 int i; 134 135 ea.ea_dmat = eba->eba_dmat; 136 ea.ea_iot = iot; 137 ea.ea_memt = memt; 138 ea.ea_ec = ec; 139 ea.ea_slot = slot; 140 slotaddr = EISA_SLOT_ADDR(slot); 141 142 /* 143 * Get a mapping for the whole slot-specific address 144 * space. If we can't, assume nothing's there but warn 145 * about it. 146 */ 147 if (bus_space_map(iot, slotaddr, EISA_SLOT_SIZE, 0, &slotioh)) { 148 printf("%s: can't map i/o space for slot %d\n", 149 self->dv_xname, slot); 150 continue; 151 } 152 153 /* Get the vendor ID bytes */ 154 for (i = 0; i < EISA_NVIDREGS; i++) { 155 #ifdef EISA_SLOTOFF_PRIMING 156 bus_space_write_1(iot, slotioh, 157 EISA_SLOTOFF_PRIMING, EISA_PRIMING_VID(i)); 158 #endif 159 ea.ea_vid[i] = bus_space_read_1(iot, slotioh, 160 EISA_SLOTOFF_VID + i); 161 } 162 163 /* Check for device existence */ 164 if (EISA_VENDID_NODEV(ea.ea_vid)) { 165 #if 0 166 printf("no device at %s slot %d\n", self->dv_xname, 167 slot); 168 printf("\t(0x%x, 0x%x)\n", ea.ea_vid[0], 169 ea.ea_vid[1]); 170 #endif 171 bus_space_unmap(iot, slotioh, EISA_SLOT_SIZE); 172 continue; 173 } 174 175 /* And check that the firmware didn't biff something badly */ 176 if (EISA_VENDID_IDDELAY(ea.ea_vid)) { 177 printf("%s slot %d not configured by BIOS?\n", 178 self->dv_xname, slot); 179 bus_space_unmap(iot, slotioh, EISA_SLOT_SIZE); 180 continue; 181 } 182 183 /* Get the product ID bytes */ 184 for (i = 0; i < EISA_NPIDREGS; i++) { 185 #ifdef EISA_SLOTOFF_PRIMING 186 bus_space_write_1(iot, slotioh, 187 EISA_SLOTOFF_PRIMING, EISA_PRIMING_PID(i)); 188 #endif 189 ea.ea_pid[i] = bus_space_read_1(iot, slotioh, 190 EISA_SLOTOFF_PID + i); 191 } 192 193 /* Create the ID string from the vendor and product IDs */ 194 ea.ea_idstring[0] = EISA_VENDID_0(ea.ea_vid); 195 ea.ea_idstring[1] = EISA_VENDID_1(ea.ea_vid); 196 ea.ea_idstring[2] = EISA_VENDID_2(ea.ea_vid); 197 ea.ea_idstring[3] = EISA_PRODID_0(ea.ea_pid); 198 ea.ea_idstring[4] = EISA_PRODID_1(ea.ea_pid); 199 ea.ea_idstring[5] = EISA_PRODID_2(ea.ea_pid); 200 ea.ea_idstring[6] = EISA_PRODID_3(ea.ea_pid); 201 ea.ea_idstring[7] = '\0'; /* sanity */ 202 203 /* We no longer need the I/O handle; free it. */ 204 bus_space_unmap(iot, slotioh, EISA_SLOT_SIZE); 205 206 /* Attach matching device. */ 207 config_found_sm(self, &ea, eisaprint, eisasubmatch); 208 } 209 } 210 211 #ifdef EISAVERBOSE 212 /* 213 * Descriptions of known vendors and devices ("products"). 214 */ 215 struct eisa_knowndev { 216 int flags; 217 char id[8]; 218 const char *name; 219 }; 220 #define EISA_KNOWNDEV_NOPROD 0x01 /* match on vendor only */ 221 222 #include <dev/eisa/eisadevs_data.h> 223 #endif /* EISAVERBOSE */ 224 225 void 226 eisa_devinfo(const char *id, char *cp, size_t cp_len) 227 { 228 const char *name; 229 int onlyvendor; 230 #ifdef EISAVERBOSE 231 const struct eisa_knowndev *edp; 232 int match; 233 const char *unmatched = "unknown "; 234 #else 235 const char *unmatched = ""; 236 #endif 237 238 onlyvendor = 0; 239 name = NULL; 240 241 #ifdef EISAVERBOSE 242 /* find the device in the table, if possible. */ 243 edp = eisa_knowndevs; 244 while (edp->name != NULL) { 245 /* check this entry for a match */ 246 if ((edp->flags & EISA_KNOWNDEV_NOPROD) != 0) 247 match = !strncmp(edp->id, id, 3); 248 else 249 match = !strcmp(edp->id, id); 250 if (match) { 251 name = edp->name; 252 onlyvendor = (edp->flags & EISA_KNOWNDEV_NOPROD) != 0; 253 break; 254 } 255 edp++; 256 } 257 #endif 258 259 if (name == NULL) 260 snprintf(cp, cp_len, "%sdevice %s", unmatched, id); 261 else if (onlyvendor) /* never if not EISAVERBOSE */ 262 snprintf(cp, cp_len, "unknown %s device %s", name, id); 263 else 264 snprintf(cp, cp_len, "%s", name); 265 } 266