This source file includes following definitions.
- geodesc_match
- geodesc_attach
- geodesc_wdogctl_cb
- geodesc_get_timecount
- sc1100_sysreset
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 #include <sys/cdefs.h>
25 #include <sys/param.h>
26 #include <sys/systm.h>
27 #include <sys/device.h>
28 #ifdef __HAVE_TIMECOUNTER
29 #include <sys/timetc.h>
30 #endif
31
32 #include <machine/bus.h>
33
34 #include <dev/pci/pcivar.h>
35 #include <dev/pci/pcidevs.h>
36
37 #include <arch/i386/pci/geodescreg.h>
38
39 struct geodesc_softc {
40 struct device sc_dev;
41 bus_space_tag_t sc_iot;
42 bus_space_handle_t sc_ioh;
43 };
44
45 int geodesc_match(struct device *, void *, void *);
46 void geodesc_attach(struct device *, struct device *, void *);
47 void sc1100_sysreset(void);
48
49 #ifndef SMALL_KERNEL
50 int geodesc_wdogctl_cb(void *, int);
51 #endif
52
53 struct cfattach geodesc_ca = {
54 sizeof(struct geodesc_softc), geodesc_match, geodesc_attach
55 };
56
57 struct cfdriver geodesc_cd = {
58 NULL, "geodesc", DV_DULL
59 };
60
61 #ifdef __HAVE_TIMECOUNTER
62 u_int geodesc_get_timecount(struct timecounter *tc);
63
64 struct timecounter geodesc_timecounter = {
65 geodesc_get_timecount,
66 0,
67 0xffffffff,
68 27000000,
69 "GEOTSC",
70 2000
71 };
72 #endif
73
74 int
75 geodesc_match(struct device *parent, void *match, void *aux)
76 {
77 struct pci_attach_args *pa = aux;
78
79 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_NS &&
80 (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_NS_SC1100_XBUS ||
81 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_NS_SCx200_XBUS))
82 return (1);
83 return (0);
84 }
85
86 #define WDSTSBITS "\20\x04WDRST\x03WDSMI\x02WDINT\x01WDOVF"
87
88 void
89 geodesc_attach(struct device *parent, struct device *self, void *aux)
90 {
91 struct geodesc_softc *sc = (void *) self;
92 struct pci_attach_args *pa = aux;
93 uint16_t cnfg, cba;
94 uint8_t sts, rev, iid;
95 pcireg_t reg;
96 extern void (*cpuresetfn)(void);
97
98 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, SC1100_F5_SCRATCHPAD);
99 sc->sc_iot = pa->pa_iot;
100 if (reg == 0 ||
101 bus_space_map(sc->sc_iot, reg, 64, 0, &sc->sc_ioh)) {
102 printf(": unable to map registers at 0x%x\n", reg);
103 return;
104 }
105 cba = bus_space_read_2(sc->sc_iot, sc->sc_ioh, GCB_CBA);
106 if (cba != reg) {
107 printf(": cba mismatch: cba 0x%x != reg 0x%x\n", cba, reg);
108 bus_space_unmap(sc->sc_iot, sc->sc_ioh, 64);
109 return;
110 }
111 sts = bus_space_read_1(sc->sc_iot, sc->sc_ioh, GCB_WDSTS);
112 cnfg = bus_space_read_2(sc->sc_iot, sc->sc_ioh, GCB_WDCNFG);
113 iid = bus_space_read_1(sc->sc_iot, sc->sc_ioh, GCB_IID);
114 rev = bus_space_read_1(sc->sc_iot, sc->sc_ioh, GCB_REV);
115
116 printf(": iid %d revision %d wdstatus %b\n", iid, rev, sts, WDSTSBITS);
117
118 #ifndef SMALL_KERNEL
119
120 bus_space_write_2(sc->sc_iot, sc->sc_ioh, GCB_WDTO, 0);
121 sts |= WDOVF_CLEAR;
122 bus_space_write_1(sc->sc_iot, sc->sc_ioh, GCB_WDSTS, sts);
123 cnfg &= ~WDCNFG_MASK;
124 cnfg |= WDTYPE1_RESET|WDPRES_DIV_512;
125 bus_space_write_2(sc->sc_iot, sc->sc_ioh, GCB_WDCNFG, cnfg);
126
127 wdog_register(sc, geodesc_wdogctl_cb);
128 #endif
129
130 #ifdef __HAVE_TIMECOUNTER
131 bus_space_write_4(sc->sc_iot, sc->sc_ioh, GCB_TSCNFG, TSC_ENABLE);
132
133 geodesc_timecounter.tc_priv = sc;
134 tc_init(&geodesc_timecounter);
135 #endif
136
137
138 cpuresetfn = sc1100_sysreset;
139 }
140
141 #ifndef SMALL_KERNEL
142 int
143 geodesc_wdogctl_cb(void *self, int period)
144 {
145 struct geodesc_softc *sc = self;
146
147 if (period > 0x03ff)
148 period = 0x03ff;
149 bus_space_write_2(sc->sc_iot, sc->sc_ioh, GCB_WDTO, period * 64);
150 return (period);
151 }
152 #endif
153
154 #ifdef __HAVE_TIMECOUNTER
155 u_int
156 geodesc_get_timecount(struct timecounter *tc)
157 {
158 struct geodesc_softc *sc = tc->tc_priv;
159
160 return (bus_space_read_4(sc->sc_iot, sc->sc_ioh, GCB_TSC));
161 }
162 #endif
163
164 void
165 sc1100_sysreset(void)
166 {
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182 outl(0xCF8, 0x80009044UL);
183 outb(0xCFC, 0x0F);
184 }