This source file includes following definitions.
- wdtprobe
- wdtattach
- wdt_is501
- wdt_8254_count
- wdt_8254_mode
- wdt_set_timeout
- wdt_timer_disable
- wdt_init_timer
- wdt_buzzer_off
- wdt_buzzer_enable
- wdt_buzzer_disable
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 #include <sys/types.h>
31 #include <sys/param.h>
32 #include <sys/device.h>
33 #include <sys/kernel.h>
34 #include <sys/proc.h>
35 #include <sys/systm.h>
36
37 #include <machine/bus.h>
38
39 #include <dev/pci/pcivar.h>
40 #include <dev/pci/pcireg.h>
41 #include <dev/pci/pcidevs.h>
42
43 #include <dev/pci/wdt50x.h>
44
45 struct wdt_softc {
46
47 struct device wdt_dev;
48
49
50 int features;
51
52
53 bus_space_tag_t iot;
54 bus_space_handle_t ioh;
55 };
56
57 int wdtprobe(struct device *, void *, void *);
58 void wdtattach(struct device *, struct device *, void *);
59
60 int wdt_is501(struct wdt_softc *);
61 void wdt_8254_count(struct wdt_softc *, int, u_int16_t);
62 void wdt_8254_mode(struct wdt_softc *, int, int);
63 int wdt_set_timeout(void *, int);
64 void wdt_init_timer(struct wdt_softc *);
65 void wdt_buzzer_off(struct wdt_softc *);
66 void wdt_timer_disable(struct wdt_softc *);
67 void wdt_buzzer_enable(struct wdt_softc *);
68
69 struct cfattach wdt_ca = {
70 sizeof(struct wdt_softc), wdtprobe, wdtattach
71 };
72
73 struct cfdriver wdt_cd = {
74 NULL, "wdt", DV_DULL
75 };
76
77 const struct pci_matchid wdt_devices[] = {
78 { PCI_VENDOR_INDCOMPSRC, PCI_PRODUCT_INDCOMPSRC_WDT50x }
79 };
80
81
82
83
84 #define WDT_8254_TC_LO 0
85 #define WDT_8254_TC_HI 1
86 #define WDT_8254_BUZZER 2
87
88
89
90
91 #define WDT_8254_BASE 0
92 #define WDT_8254_CTL (WDT_8254_BASE + 3)
93 #define WDT_DISABLE_TIMER 7
94 #define WDT_ENABLE_TIMER 7
95
96
97
98
99 #define WDT_STATUS_REG 4
100 #define WDT_START_BUZZER 4
101 #define WDT_TEMPERATURE 5
102 #define WDT_STOP_BUZZER 5
103
104 int
105 wdtprobe(struct device *parent, void *match, void *aux)
106 {
107 return (pci_matchbyid((struct pci_attach_args *)aux, wdt_devices,
108 sizeof(wdt_devices)/sizeof(wdt_devices[0])));
109 }
110
111 void
112 wdtattach(struct device *parent, struct device *self, void *aux)
113 {
114 struct wdt_softc *wdt = (struct wdt_softc *)self;
115 struct pci_attach_args *const pa = (struct pci_attach_args *)aux;
116 bus_size_t iosize;
117
118
119 if (pci_mapreg_map(pa, 0x18, PCI_MAPREG_TYPE_IO, 0,
120 &wdt->iot, &wdt->ioh, NULL, &iosize, 0) != 0) {
121 printf("%s: couldn't find PCI I/O region\n",
122 wdt->wdt_dev.dv_xname);
123 return;
124 }
125
126
127 if (iosize != (bus_size_t)16) {
128 printf("%s: invalid I/O region size\n",
129 wdt->wdt_dev.dv_xname);
130 return;
131 }
132
133
134
135
136 if (wdt_is501(wdt))
137 wdt->features = 1;
138 else
139 wdt->features = 0;
140
141 if (wdt->features) {
142
143
144
145
146 wdt_buzzer_off(wdt);
147
148 wdt_buzzer_enable(wdt);
149 }
150
151
152 wdt_init_timer(wdt);
153
154
155
156
157 wdt_timer_disable(wdt);
158
159
160
161
162 wdog_register(wdt, wdt_set_timeout);
163 }
164
165
166
167
168
169
170 int
171 wdt_is501(struct wdt_softc *wdt)
172 {
173
174
175
176
177
178 int v = bus_space_read_1(wdt->iot, wdt->ioh, WDT_TEMPERATURE);
179
180
181 if (v == 0 || v == 0xFF)
182 return(0);
183
184 return(1);
185 }
186
187
188
189
190
191
192 void
193 wdt_8254_count(struct wdt_softc *wdt, int counter, u_int16_t v)
194 {
195 bus_space_write_1(wdt->iot, wdt->ioh,
196 WDT_8254_BASE + counter, v & 0xFF);
197 bus_space_write_1(wdt->iot, wdt->ioh, WDT_8254_BASE + counter, v >> 8);
198 }
199
200
201
202
203
204
205 void
206 wdt_8254_mode(struct wdt_softc *wdt, int counter, int mode)
207 {
208 bus_space_write_1(wdt->iot, wdt->ioh, WDT_8254_CTL,
209 (counter << 6) | 0x30 | (mode << 1));
210 }
211
212
213
214
215
216
217
218 int
219 wdt_set_timeout(void *self, int seconds)
220 {
221 struct wdt_softc *wdt = (struct wdt_softc *)self;
222
223 u_int16_t v;
224 int s;
225
226 s = splclock();
227
228 wdt_timer_disable(wdt);
229
230 if (seconds == 0) {
231 splx(s);
232 return (0);
233 } else if (seconds < 2)
234 seconds = 2;
235 else if (seconds > 1800)
236 seconds = 1800;
237
238
239 v = (u_int16_t)seconds * 50;
240
241
242 wdt_8254_count(wdt, WDT_8254_TC_HI, v);
243
244
245 bus_space_write_1(wdt->iot, wdt->ioh, WDT_ENABLE_TIMER, 0);
246
247 splx(s);
248
249 return (seconds);
250 }
251
252
253
254
255
256
257
258 void
259 wdt_timer_disable(struct wdt_softc *wdt)
260 {
261 (void)bus_space_read_1(wdt->iot, wdt->ioh, WDT_DISABLE_TIMER);
262 }
263
264
265
266
267
268
269
270
271 void
272 wdt_init_timer(struct wdt_softc *wdt)
273 {
274 wdt_8254_mode(wdt, WDT_8254_TC_LO, 3);
275 wdt_8254_mode(wdt, WDT_8254_TC_HI, 2);
276 wdt_8254_count(wdt, WDT_8254_TC_LO, 41666);
277 }
278
279
280
281
282
283
284
285
286
287
288 void
289 wdt_buzzer_off(struct wdt_softc *wdt)
290 {
291 bus_space_write_1(wdt->iot, wdt->ioh, WDT_STOP_BUZZER, 0);
292 }
293
294 #ifndef WDT_DISABLE_BUZZER
295
296
297
298
299
300 void
301 wdt_buzzer_enable(struct wdt_softc *wdt)
302 {
303 bus_space_write_1(wdt->iot, wdt->ioh, WDT_8254_BUZZER, 1);
304 wdt_8254_mode(wdt, WDT_8254_BUZZER, 1);
305 }
306 #else
307
308
309
310
311
312
313 void
314 wdt_buzzer_disable(struct wdt_softc *wdt)
315 {
316 wdt_8254_mode(wdt, WDT_8254_BUZZER, 0);
317 }
318 #endif