comparison vordog.c @ 0:71475f5afa92

Watchdog for Vortex86 6071 on FreeBSD
author Thinker K.F. Li <thinker@branda.to>
date Tue, 08 Jul 2008 09:57:54 +0800
parents
children 0b9854adb86c
comparison
equal deleted inserted replaced
-1:000000000000 0:71475f5afa92
1 #include <sys/param.h>
2 #include <sys/bus.h>
3 #include <sys/conf.h>
4 #include <sys/kernel.h>
5 #include <sys/module.h>
6 #include <sys/systm.h>
7 #include <sys/proc.h>
8 #include <sys/ioccom.h>
9 #include <sys/types.h>
10 #include <sys/malloc.h>
11 #include "vordog.h"
12
13 #if 1
14 #undef __FreeBSD_version
15 #define __FreeBSD_version 800029
16 #endif
17
18 #define VD_STATUS 0x841
19 #define VD_INITVAL 0x84a
20 #define VD_CTR 0x84b
21
22 typedef struct vd_softc {
23 struct cdev *_cdev;
24 device_t dev;
25 int open_cnt;
26 int init_val;
27 } *vd_softc_t;
28
29 #define CDEV_2_SOFTC(_cdev) ((_cdev)->si_drv1)
30
31 static int
32 vordog_open(struct cdev *dev, int oflags, int devtype, struct thread *td) {
33 vd_softc_t sc;
34
35 printf("vordog_open\n");
36 sc = CDEV_2_SOFTC(dev);
37 sc->open_cnt++;
38
39 return 0;
40 }
41
42 static int
43 vordog_close(struct cdev *dev, int fflag, int devtype, struct thread *td) {
44 vd_softc_t sc;
45
46 printf("vordog_close\n");
47 sc = CDEV_2_SOFTC(dev);
48 sc->open_cnt--;
49
50 return 0;
51 }
52
53 static int
54 vordog_go_detach(void) {
55 devclass_t vd_dc;
56 device_t vd_dev, nexus_dev;
57 int r;
58
59 printf("go_detach 1\n");
60 vd_dc = devclass_find("vordog");
61 if(vd_dc == NULL)
62 return EINVAL;
63
64 printf("go_detach 2\n");
65 vd_dev = devclass_get_device(vd_dc, 0);
66 if(vd_dev == NULL)
67 return EINVAL;
68
69 printf("go_detach 3\n");
70 nexus_dev = device_get_parent(vd_dev);
71 if(nexus_dev == NULL)
72 return EINVAL;
73
74 printf("go_detach 4\n");
75 r = device_delete_child(nexus_dev, vd_dev);
76 return r;
77 }
78
79 static void
80 setup_timer(vordog_cfg_t cfg) {
81 int val;
82 #define VD_TIMER_RST 0xc
83
84 #if 0
85 outb(VD_STATUS, 0xc0); /* Clear events or it would be reset
86 * immediately, since it is setted
87 * by last timeout before PCIRST.
88 */
89 #endif
90 val = cfg->init_val & 0xff;
91 printf("setup_timer 1 (%x)\n", val);
92 pause("vordog setup", hz);
93 outb(VD_INITVAL, val);
94 printf("setup_timer 2\n");
95 val = 0x80 | ((cfg->unit & 0x3) << 4) | VD_TIMER_RST;
96 printf("setup_timer 3 (%x)\n", val);
97 pause("vordog setup", hz);
98 outb(VD_CTR, val);
99 printf("setup_timer 4\n");
100 }
101
102 static void
103 reset_timer(int init_val) {
104 #if 0
105 printf("reset_timer 1\n");
106 pause("vordog setup", hz);
107 outb(VD_INITVAL, init_val);
108 #endif
109 printf("reset_timer 2\n");
110 pause("vordog setup", hz);
111 outb(VD_STATUS, 0xc0);
112 printf("reset_timer 3\n");
113 pause("vordog setup", hz);
114 }
115
116 static void
117 disable_timer(void) {
118 outb(VD_CTR, 0);
119 outb(VD_STATUS, 0xc0);
120 }
121
122 static int
123 vordog_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
124 int fflag, struct thread *td) {
125 int r = 0;
126 vd_softc_t sc;
127 vordog_cfg_t cfg;
128
129 sc = CDEV_2_SOFTC(dev);
130 switch(cmd) {
131 case VDCTL_ENABLE:
132 printf("VDCTL_ENABLE\n");
133 cfg = (vordog_cfg_t)data;
134 sc->init_val = cfg->init_val & 0xff;
135 setup_timer(cfg);
136 break;
137 case VDCTL_RESET:
138 printf("VDCTL_RESET\n");
139 reset_timer(sc->init_val);
140 break;
141 case VDCTL_DISABLE:
142 printf("VDCTL_DISABLE\n");
143 disable_timer();
144 break;
145 default:
146 r = EINVAL;
147 }
148 return r;
149 }
150
151 struct cdevsw vordog_cdevsw = {
152 .d_version = D_VERSION,
153 .d_open = vordog_open,
154 .d_close = vordog_close,
155 .d_ioctl = vordog_ioctl,
156 .d_name = "vordog",
157 };
158
159 static void vordog_identify(driver_t *driver, device_t parent) {
160 device_t vordog;
161
162 /* make sure vordog device is not in the bus. */
163 vordog = device_find_child(parent, "vordog", 0);
164 if(vordog != NULL) {
165 printf("vordog is still existing!");
166 return;
167 }
168 vordog = BUS_ADD_CHILD(parent, 10, "vordog", 0);
169 printf("vordog_identify\n");
170 }
171
172 static int vordog_probe(device_t dev) {
173 int b;
174
175 printf("vordog_probe\n");
176 b = inb(VD_INITVAL);
177 printf("init val: %x\n", b);
178 b = inb(VD_CTR);
179 printf("ctr: %x\n", b);
180 b = inb(VD_STATUS);
181 printf("status: %x\n", b);
182 return 0;
183 }
184
185 static int vordog_attach(device_t dev) {
186 vd_softc_t sc;
187 struct cdev *_cdev;
188
189 printf("vordog_attach 1\n");
190
191 sc = (vd_softc_t)malloc(sizeof(struct vd_softc), M_TEMP, M_WAITOK);
192 if(sc == NULL)
193 return ENOMEM;
194
195 printf("vordog_attach 2\n");
196 _cdev = make_dev(&vordog_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "vordog0");
197 if(_cdev == NULL) {
198 free(sc, M_TEMP);
199 return EINVAL;
200 }
201
202 sc->_cdev = _cdev;
203 sc->dev = dev;
204
205 printf("vordog_attach 3\n");
206 device_set_softc(dev, sc);
207 CDEV_2_SOFTC(_cdev) = sc;
208
209 sc->open_cnt = 0;
210 sc->init_val = 0;
211
212 return 0;
213 }
214
215 static int vordog_detach(device_t dev) {
216 vd_softc_t sc;
217 struct cdev *_cdev;
218
219 printf("vordog_detach 1\n");
220 sc = device_get_softc(dev);
221 if(sc->open_cnt != 0)
222 return EBUSY;
223
224 printf("vordog_detach 2\n");
225 _cdev = sc->_cdev;
226
227 printf("vordog_detach 3\n");
228 destroy_dev(_cdev);
229 printf("vordog_detach 4\n");
230
231 free(sc, M_TEMP);
232
233 return 0;
234 }
235
236 static device_method_t vordog_methods[] = {
237 DEVMETHOD(device_identify, vordog_identify),
238 DEVMETHOD(device_probe, vordog_probe),
239 DEVMETHOD(device_attach, vordog_attach),
240 DEVMETHOD(device_detach, vordog_detach),
241 {0, 0}
242 };
243
244 static driver_t vordog_driver = {
245 "vordog",
246 vordog_methods,
247 0,
248 };
249
250 static int
251 vordog_evh(module_t mod, int cmd, void *arg) {
252 int r = 0;
253
254 switch(cmd) {
255 case MOD_LOAD:
256 printf("MOD_LOAD\n");
257 break;
258 case MOD_UNLOAD:
259 printf("MOD_UNLOAD\n");
260 vordog_go_detach(); /* remove device from parent */
261 break;
262 case MOD_SHUTDOWN:
263 printf("MOD_SHUTDOWN\n");
264 break;
265 default:
266 r = EINVAL;
267 break;
268 }
269 return r;
270 }
271
272 static devclass_t vordog_devclass;
273
274 DRIVER_MODULE(vordog, nexus, vordog_driver, vordog_devclass,
275 vordog_evh, NULL);