Annotation of funnyos/kern/kern_devconfig.c, Revision 1.4
1.1 init 1: /*
1.4 ! init 2: * $Id: kern_devconfig.c,v 1.3 2007/10/16 13:29:59 init Exp $
1.1 init 3: */
4: #include <sys/types.h>
5: #include <sys/device.h>
6: #include <sys/kern_devconfig.h>
7: #include <sys/mem.h>
8: #include <libkern/string.h>
9: #include <libkern/printf.h>
10:
1.4 ! init 11: /* #define DEVCONFIG_DEBUG */
1.1 init 12:
13: #ifdef DEVCONFIG_DEBUG
14: #define DPRINTF(x...) do { printf(x); } while (0)
15: #else
16: #define DPRINTF(x...) { }
17: #endif
18:
19: //extern struct device devlist[];
20: //extern uint8_t ndevices;
21:
22: /* system root device */
23: extern struct device *rootdev;
24:
25: /* config stuff */
26: extern struct attachinfo config_attachinfo[];
27: extern struct driverinfo config_driverinfo[];
28:
29:
30: void
31: devconfig_recurse(void)
32: {
33: /*
34: * Recursive attach all device tree.
35: * Steps involved:
36: * - find root device in device list and attach it
37: * - for every root's child do:
38: * - attach this child
39: * - for every child's child do:
40: * - attach that child
41: * - ...and so on.
42: */
43: devconfig_attach_root();
44: // devconfig_attach(&rootdev);
45: }
46:
47:
48: void
49: devconfig_attach_root(void)
50: {
51: /*
52: * Attach root and call devconfig_attach on itself (proceeding with its children).
53: */
54: int retval;
55: struct driver *drp;
56: struct driverinfo *dip;
57:
58: DPRINTF("devconfig_attach_root: entering\n");
59:
60: /* allocate memory for root device */
61: rootdev = kmalloc(sizeof(struct device));
62: if (rootdev == NULL)
63: panic("failed to allocate space for rootdev\n");
64: /* NOTREACHED */
65:
66: /* find root's driverinfo */
67: dip = devconfig_finddriverinfo("root");
68:
69: drp = dip->di_driverp;
70:
71: /* allocate space for root's devdata */
72: rootdev->dv_devdata = kmalloc(drp->dr_ddsize);
73: if(rootdev->dv_devdata == NULL)
74: panic("failed to allocate space for rootdev devdata\n");
75: /* NOTREACHED */
76:
77: /* increment number of this driver's instances */
78: dip->di_ninstances++;
79: rootdev->dv_minor = dip->di_ninstances;
80:
81: rootdev->dv_name = dip->di_dname;
82:
83: /* link dv_parent into root itself */
84: rootdev->dv_parent = rootdev;
85:
86: printf("%s/%d at %s/%d loc 0x%x flags 0x%x: ", rootdev->dv_name, rootdev->dv_minor,
87: rootdev->dv_parent->dv_name, rootdev->dv_parent->dv_minor, 0, 0);
88:
89: /* attach root; should never fail */
90: retval = drp->dr_attach(rootdev, 0, 0);
91:
92: if (retval == -1)
93: panic("failed to attach rootdev\n");
94: /* NOTREACHED */
95:
96: /* rootdev has been attached, so activate it */
97: rootdev->dv_active = 1;
98:
99: /* attach all other devices */
100: devconfig_attach_childs(rootdev);
101:
102: }
103:
104: int
105: devconfig_attach_childs(struct device *pdevp)
106: {
107: /*
108: * Attach device childs, if any.
109: * XXX Allocate space for struct device and its xxx_dd
110: */
111: int retval;
112: struct device *cdevp;
113: struct driver *drp;
114: struct driverinfo *dip;
115: struct attachinfo *aip = config_attachinfo;
116:
117: DPRINTF("devconfig_attach_childs: entering for %s/%d\n", pdevp->dv_name, pdevp->dv_minor);
118:
119: /* look for potential children in config_attachinfo table */
120: while(aip->ai_cname != NULL) {
121: if (strncmp(aip->ai_pname, pdevp->dv_name, DVNAMELEN - 1) == 0 && aip->ai_pminor == pdevp->dv_minor) {
122: /*
123: * It is our child.
124: */
125:
126: /* find child's driverinfo */
127: dip = devconfig_finddriverinfo(aip->ai_cname);
128:
129: /* allocate space for child's device */
130: cdevp = kmalloc(sizeof(struct device));
131: if (cdevp == NULL)
132: panic("failed to allocate space for %s device\n", aip->ai_cname);
133: /* NOTREACHED */
134:
135: /* link with parent */
136: cdevp->dv_parent = pdevp;
137:
138: drp = dip->di_driverp;
139:
140: /* allocate space for device's devdata */
141: cdevp->dv_devdata = kmalloc(drp->dr_ddsize);
142: if (cdevp->dv_devdata == NULL)
143: panic("failed to allocate space for %s devdata\n");
144: /* NOTREACHED */
145:
146: /* increment number of driver's instances */
147: dip->di_ninstances++;
148:
149: cdevp->dv_name = dip->di_dname;
150: cdevp->dv_minor = dip->di_ninstances;
151:
152: /* XXX what about locator (aip->ai_locator)? */
153:
154: printf("%s/%d at %s/%d loc 0x%x flags 0x%x: ", cdevp->dv_name, cdevp->dv_minor,
155: pdevp->dv_name, pdevp->dv_minor, aip->ai_locator, aip->ai_flags);
156:
157: /* try to attach this device */
158: retval = drp->dr_attach(cdevp, aip->ai_locator, aip->ai_flags);
159: if (retval == -1) {
160: /*
161: * Attachment failed.
162: */
163:
164: /* XXX what should we do? */
165: printf("disabling %s/%d\n", cdevp->dv_name, cdevp->dv_minor);
166:
167: /* TODO kfree devdata and device */
168:
1.2 init 169: /* XXX next aip */
170: aip++;
171:
1.1 init 172: continue;
173: /* NOTREACHED */
174: }
175:
176: /*
177: * Attachment completed.
178: */
179:
180: /* activate device */
181: cdevp->dv_active = 1;
182:
183: /* XXX think about recursion */
184:
185: /* recursive attach this child's children */
1.2 init 186: devconfig_attach_childs(cdevp);
1.1 init 187:
188: }
189:
190: /* next attachinfo in table */
191: aip++;
192: }
193:
194: }
195:
196: #if 0
197: void
198: devconfig_iterate(void)
199: {
200: struct device *devp = devlist;
201:
202: printf("Entered devconfig phase\n");
203:
204: while(devp->dv_attach != NULL) {
205: /*
206: * Iterative attach all devices in list.
207: */
208: if (! devp->dv_active && (devp->dv_parent->dv_active || devp->dv_parent == devp)) {
209:
210: printf("%s/%d at %s/%d loc 0x%x: ", devp->dv_name, devp->dv_minor, devp->dv_parent->dv_name,
211: devp->dv_parent->dv_minor, devp->dv_locator);
212:
213: /* call attach_subr and activate device if it returns 0 */
214: if (devp->dv_attach(devp) == 0) {
215: /* driver returns okay; mark device as active */
216: devp->dv_active = 1;
217: }
218: else {
219: /* attachment failed */
220: printf("disabling %s/%d\n", devp->dv_name, devp->dv_minor);
221: }
222: }
223:
224: devp++;
225: }
226:
227: printf("Exited devconfig phase\n");
228: }
229:
230:
231: int
232: devconfig_target(struct device *devp)
233: {
234: /*
235: * Recursive attach (subtree) nodes upto already active parent or (root).
236: */
237:
238: if (devp == NULL)
239: return(-1);
240:
241: /* attach parent if it's not (root) or not activated yet */
242: if (devp->dv_parent != devp && ! devp->dv_parent->dv_active) {
243:
244: if (devconfig_target(devp->dv_parent) == -1)
245: return(-1);
246: }
247:
248: printf("%s/%d at %s/%d\n", devp->dv_name, devp->dv_minor,
249: devp->dv_parent->dv_name, devp->dv_parent->dv_minor);
250: if (devp->dv_attach(devp) == 0) {
251: /* attached */
252: devp->dv_active = 1;
253:
254: return(0);
255: }
256: else {
257: /* failed */
258: printf("disabling %s/%d\n", devp->dv_name, devp->dv_minor);
259:
260: /* XXX maybe it is easier to panic here? */
261: /* panic(XXX) */
262:
263: return(-1);
264: }
265: }
266:
267:
268: struct device
269: *devconfig_findbyname(const char *dv_name, const uint8_t dv_minor)
270: {
271: /*
272: * Return pointer to device dv_name/dv_minor.
273: */
274: struct device *devp = devlist;
275:
276: while(devp->dv_name) {
277: if (strncmp(devp->dv_name, dv_name, DVNAMELEN - 1) == 0 && devp->dv_minor == dv_minor)
278: return (devp);
279: }
280:
281: /* nothing has been found */
282: return(NULL);
283: }
284: #endif /* not 0 */
285:
286: struct driverinfo
287: *devconfig_finddriverinfo(const char *dname)
288: {
289: /*
290: * Return associated with dname driver (from config_driverinfo[])
291: * Will cause SYSTEM PANIC if can't find associated driver.
292: */
293: struct driverinfo *dip = config_driverinfo;
294:
295: while(dip->di_dname != NULL) {
296: if (strncmp(dname, dip->di_dname, DVNAMELEN - 1) == 0)
297: return(dip);
298:
299: dip++;
300: }
301:
302: panic("failed to find driverinfo entry for %s\n", dname);
303: /* NOTREACHED */
304:
305: return(NULL);
306: }
307:
308:
CVSweb