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