1 /* $NetBSD: tc.c,v 1.49 2009/05/12 13:21:22 cegger Exp $ */
4 * Copyright (c) 1994, 1995 Carnegie-Mellon University.
7 * Author: Chris G. Demetriou
9 * Permission to use, copy, modify and distribute this software and
10 * its documentation is hereby granted, provided that both the copyright
11 * notice and this permission notice appear in all copies of the
12 * software, derivative works or modified versions, and any portions
13 * thereof, and that both notices appear in supporting documentation.
15 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
16 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
17 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
19 * Carnegie Mellon requests users of this software to return to
21 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
22 * School of Computer Science
23 * Carnegie Mellon University
24 * Pittsburgh PA 15213-3890
26 * any improvements or extensions that they make and grant Carnegie the
27 * rights to redistribute these changes.
30 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: tc.c,v 1.49 2009/05/12 13:21:22 cegger Exp $");
33 #include "opt_tcverbose.h"
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/device.h>
39 #include <machine/cpu.h> /* for badaddr */
41 #include <dev/tc/tcreg.h>
42 #include <dev/tc/tcvar.h>
43 #include <dev/tc/tcdevs.h>
47 /* Definition of the driver for autoconfig. */
48 static int tcmatch(device_t
, cfdata_t
, void *);
50 CFATTACH_DECL(tc
, sizeof(struct tc_softc
),
51 tcmatch
, tcattach
, NULL
, NULL
);
53 extern struct cfdriver tc_cd
;
55 static int tcprint(void *, const char *);
56 static void tc_devinfo(const char *, char *, size_t);
59 tcmatch(device_t parent
, cfdata_t cf
, void *aux
)
61 struct tcbus_attach_args
*tba
= aux
;
63 if (strcmp(tba
->tba_busname
, cf
->cf_name
))
70 tcattach(device_t parent
, device_t self
, void *aux
)
72 struct tc_softc
*sc
= device_private(self
);
73 struct tcbus_attach_args
*tba
= aux
;
74 struct tc_attach_args ta
;
75 const struct tc_builtin
*builtin
;
76 struct tc_slotdesc
*slot
;
81 printf(": %s MHz clock\n",
82 tba
->tba_speed
== TC_SPEED_25_MHZ
? "25" : "12.5");
85 * Save important CPU/chipset information.
87 sc
->sc_speed
= tba
->tba_speed
;
88 sc
->sc_nslots
= tba
->tba_nslots
;
89 sc
->sc_slots
= tba
->tba_slots
;
90 sc
->sc_intr_evcnt
= tba
->tba_intr_evcnt
;
91 sc
->sc_intr_establish
= tba
->tba_intr_establish
;
92 sc
->sc_intr_disestablish
= tba
->tba_intr_disestablish
;
93 sc
->sc_get_dma_tag
= tba
->tba_get_dma_tag
;
96 * Try to configure each built-in device
98 for (i
= 0; i
< tba
->tba_nbuiltins
; i
++) {
99 builtin
= &tba
->tba_builtins
[i
];
102 if (builtin
->tcb_slot
> sc
->sc_nslots
)
103 panic("tcattach: builtin %d slot > nslots", i
);
106 * Make sure device is really there, because some
107 * built-in devices are really optional.
109 tcaddr
= sc
->sc_slots
[builtin
->tcb_slot
].tcs_addr
+
111 if (tc_badaddr(tcaddr
))
115 * Set up the device attachment information.
117 strncpy(ta
.ta_modname
, builtin
->tcb_modname
, TC_ROM_LLEN
);
118 ta
.ta_memt
= tba
->tba_memt
;
119 ta
.ta_dmat
= (*sc
->sc_get_dma_tag
)(builtin
->tcb_slot
);
120 ta
.ta_modname
[TC_ROM_LLEN
] = '\0';
121 ta
.ta_slot
= builtin
->tcb_slot
;
122 ta
.ta_offset
= builtin
->tcb_offset
;
124 ta
.ta_cookie
= builtin
->tcb_cookie
;
125 ta
.ta_busspeed
= sc
->sc_speed
;
128 * Mark the slot as used, so we don't check it later.
130 sc
->sc_slots
[builtin
->tcb_slot
].tcs_used
= 1;
132 locs
[TCCF_SLOT
] = builtin
->tcb_slot
;
133 locs
[TCCF_OFFSET
] = builtin
->tcb_offset
;
137 config_found_sm_loc(self
, "tc", locs
, &ta
,
138 tcprint
, config_stdsubmatch
);
142 * Try to configure each unused slot, last to first.
144 for (i
= sc
->sc_nslots
- 1; i
>= 0; i
--) {
145 slot
= &sc
->sc_slots
[i
];
147 /* If already checked above, don't look again now. */
152 * Make sure something is there, and find out what it is.
154 tcaddr
= slot
->tcs_addr
;
155 if (tc_badaddr(tcaddr
))
157 if (tc_checkslot(tcaddr
, ta
.ta_modname
) == 0)
161 * Set up the rest of the attachment information.
163 ta
.ta_memt
= tba
->tba_memt
;
164 ta
.ta_dmat
= (*sc
->sc_get_dma_tag
)(i
);
168 ta
.ta_cookie
= slot
->tcs_cookie
;
171 * Mark the slot as used.
176 locs
[TCCF_OFFSET
] = 0;
180 config_found_sm_loc(self
, "tc", locs
, &ta
,
181 tcprint
, config_stdsubmatch
);
186 tcprint(void *aux
, const char *pnp
)
188 struct tc_attach_args
*ta
= aux
;
192 tc_devinfo(ta
->ta_modname
, devinfo
, sizeof(devinfo
));
193 aprint_normal("%s at %s", devinfo
, pnp
);
195 aprint_normal(" slot %d offset 0x%x", ta
->ta_slot
, ta
->ta_offset
);
200 static const tc_offset_t tc_slot_romoffs
[] = {
208 tc_checkslot(tc_addr_t slotbase
, char *namep
)
210 struct tc_rommap
*romp
;
213 for (i
= 0; i
< __arraycount(tc_slot_romoffs
); i
++) {
214 romp
= (struct tc_rommap
*)
215 (slotbase
+ tc_slot_romoffs
[i
]);
217 switch (romp
->tcr_width
.v
) {
227 if (romp
->tcr_stride
.v
!= 4)
230 for (j
= 0; j
< 4; j
++)
231 if (romp
->tcr_test
[j
+0*romp
->tcr_stride
.v
] != 0x55 ||
232 romp
->tcr_test
[j
+1*romp
->tcr_stride
.v
] != 0x00 ||
233 romp
->tcr_test
[j
+2*romp
->tcr_stride
.v
] != 0xaa ||
234 romp
->tcr_test
[j
+3*romp
->tcr_stride
.v
] != 0xff)
237 for (j
= 0; j
< TC_ROM_LLEN
; j
++)
238 namep
[j
] = romp
->tcr_modname
[j
].v
;
246 tc_intr_evcnt(device_t dev
, void *cookie
)
248 struct tc_softc
*sc
= device_lookup_private(&tc_cd
, 0);
250 return ((*sc
->sc_intr_evcnt
)(dev
, cookie
));
254 tc_intr_establish(device_t dev
, void *cookie
, int level
,
255 int (*handler
)(void *), void *arg
)
257 struct tc_softc
*sc
= device_lookup_private(&tc_cd
, 0);
259 (*sc
->sc_intr_establish
)(dev
, cookie
, level
, handler
, arg
);
263 tc_intr_disestablish(device_t dev
, void *cookie
)
265 struct tc_softc
*sc
= device_lookup_private(&tc_cd
, 0);
267 (*sc
->sc_intr_disestablish
)(dev
, cookie
);
272 * Descriptions of of known devices.
275 const char *id
, *driver
, *description
;
278 #include <dev/tc/tcdevs_data.h>
279 #endif /* TCVERBOSE */
282 tc_devinfo(const char *id
, char *cp
, size_t l
)
284 const char *driver
, *description
;
286 const struct tc_knowndev
*tdp
;
288 const char *unmatched
= "unknown ";
290 const char *unmatched
= "";
297 /* find the device in the table, if possible. */
299 while (tdp
->id
!= NULL
) {
300 /* check this entry for a match */
301 match
= !strcmp(tdp
->id
, id
);
303 driver
= tdp
->driver
;
304 description
= tdp
->description
;
312 snprintf(cp
, l
, "%sdevice %s", unmatched
, id
);
314 snprintf(cp
, l
, "%s (%s)", driver
, description
);