Annotation of funnyos/kern/kern_devconfig.c, Revision 1.8
1.1 init 1: /*
1.8 ! init 2: * $Id: kern_devconfig.c,v 1.7 2007/11/01 13:22:08 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>
1.8 ! init 8: #include <sys/kern_irq.h>
1.1 init 9: #include <libkern/string.h>
10: #include <libkern/printf.h>
11:
1.4 init 12: /* #define DEVCONFIG_DEBUG */
1.1 init 13:
14: #ifdef DEVCONFIG_DEBUG
15: #define DPRINTF(x...) do { printf(x); } while (0)
16: #else
17: #define DPRINTF(x...) { }
18: #endif
19:
20:
21: /* system root device */
22: extern struct device *rootdev;
23:
24: /* config stuff */
25: extern struct attachinfo config_attachinfo[];
26: extern struct driverinfo config_driverinfo[];
27:
28:
29: void
30: devconfig_recurse(void)
31: {
32: /*
33: * Recursive attach all device tree.
34: * Steps involved:
35: * - find root device in device list and attach it
36: * - for every root's child do:
37: * - attach this child
38: * - for every child's child do:
39: * - attach that child
40: * - ...and so on.
41: */
42: devconfig_attach_root();
43: }
44:
45:
46: void
47: devconfig_attach_root(void)
48: {
49: /*
50: * Attach root and call devconfig_attach on itself (proceeding with its children).
51: */
52: int retval;
53: struct driver *drp;
54: struct driverinfo *dip;
55:
56: DPRINTF("devconfig_attach_root: entering\n");
57:
58: /* allocate memory for root device */
59: rootdev = kmalloc(sizeof(struct device));
60: if (rootdev == NULL)
61: panic("failed to allocate space for rootdev\n");
62: /* NOTREACHED */
63:
64: /* find root's driverinfo */
65: dip = devconfig_finddriverinfo("root");
66:
67: drp = dip->di_driverp;
68:
69: /* allocate space for root's devdata */
70: rootdev->dv_devdata = kmalloc(drp->dr_ddsize);
71: if(rootdev->dv_devdata == NULL)
72: panic("failed to allocate space for rootdev devdata\n");
73: /* NOTREACHED */
74:
75: /* increment number of this driver's instances */
76: dip->di_ninstances++;
77: rootdev->dv_minor = dip->di_ninstances;
78:
79: rootdev->dv_name = dip->di_dname;
80:
81: /* link dv_parent into root itself */
82: rootdev->dv_parent = rootdev;
83:
84: printf("%s/%d at %s/%d loc 0x%x flags 0x%x: ", rootdev->dv_name, rootdev->dv_minor,
85: rootdev->dv_parent->dv_name, rootdev->dv_parent->dv_minor, 0, 0);
86:
87: /* attach root; should never fail */
88: retval = drp->dr_attach(rootdev, 0, 0);
89:
1.6 init 90: if (retval != 0)
1.1 init 91: panic("failed to attach rootdev\n");
92: /* NOTREACHED */
93:
94: /* rootdev has been attached, so activate it */
95: rootdev->dv_active = 1;
96:
97: /* attach all other devices */
98: devconfig_attach_childs(rootdev);
99:
100: }
101:
102: int
103: devconfig_attach_childs(struct device *pdevp)
104: {
105: /*
106: * Attach device childs, if any.
1.7 init 107: * Allocate space for struct device and its xxx_dd
1.1 init 108: */
109: int retval;
110: struct device *cdevp;
111: struct driver *drp;
112: struct driverinfo *dip;
113: struct attachinfo *aip = config_attachinfo;
114:
115: DPRINTF("devconfig_attach_childs: entering for %s/%d\n", pdevp->dv_name, pdevp->dv_minor);
116:
117: /* look for potential children in config_attachinfo table */
118: while(aip->ai_cname != NULL) {
119: if (strncmp(aip->ai_pname, pdevp->dv_name, DVNAMELEN - 1) == 0 && aip->ai_pminor == pdevp->dv_minor) {
120: /*
121: * It is our child.
122: */
123:
124: /* find child's driverinfo */
125: dip = devconfig_finddriverinfo(aip->ai_cname);
126:
127: /* allocate space for child's device */
128: cdevp = kmalloc(sizeof(struct device));
129: if (cdevp == NULL)
130: panic("failed to allocate space for %s device\n", aip->ai_cname);
131: /* NOTREACHED */
132:
133: /* link with parent */
134: cdevp->dv_parent = pdevp;
135:
136: drp = dip->di_driverp;
137:
138: /* allocate space for device's devdata */
139: cdevp->dv_devdata = kmalloc(drp->dr_ddsize);
140: if (cdevp->dv_devdata == NULL)
141: panic("failed to allocate space for %s devdata\n");
142: /* NOTREACHED */
143:
144: /* increment number of driver's instances */
145: dip->di_ninstances++;
146:
147: cdevp->dv_name = dip->di_dname;
148: cdevp->dv_minor = dip->di_ninstances;
149:
150: printf("%s/%d at %s/%d loc 0x%x flags 0x%x: ", cdevp->dv_name, cdevp->dv_minor,
151: pdevp->dv_name, pdevp->dv_minor, aip->ai_locator, aip->ai_flags);
152:
153: /* try to attach this device */
154: retval = drp->dr_attach(cdevp, aip->ai_locator, aip->ai_flags);
1.6 init 155: if (retval != 0) {
1.1 init 156: /*
157: * Attachment failed.
158: */
159:
160: /* XXX what should we do? */
161: printf("disabling %s/%d\n", cdevp->dv_name, cdevp->dv_minor);
162:
163: /* TODO kfree devdata and device */
164:
1.7 init 165: /* next aip */
1.2 init 166: aip++;
167:
1.1 init 168: continue;
169: /* NOTREACHED */
170: }
171:
172: /*
173: * Attachment completed.
174: */
175:
176: /* activate device */
177: cdevp->dv_active = 1;
1.8 ! init 178:
! 179: /* if device has interrupt handler, establish it */
! 180: if (drp->dr_interrupt != NULL && aip->ai_intrno != 0) {
! 181: DPRINTF("devconfig_attach_childs: establishing interrupt %d for %s/%d\n",
! 182: aip->ai_intrno, cdevp->dv_name, cdevp->dv_minor);
! 183: intr_establish(aip->ai_intrno, cdevp, drp->dr_interrupt);
! 184: }
1.1 init 185:
186: /* recursive attach this child's children */
1.2 init 187: devconfig_attach_childs(cdevp);
1.1 init 188:
189: }
190:
191: /* next attachinfo in table */
192: aip++;
193: }
194:
195: }
196:
197:
198: struct driverinfo
199: *devconfig_finddriverinfo(const char *dname)
200: {
201: /*
202: * Return associated with dname driver (from config_driverinfo[])
203: * Will cause SYSTEM PANIC if can't find associated driver.
204: */
205: struct driverinfo *dip = config_driverinfo;
206:
207: while(dip->di_dname != NULL) {
208: if (strncmp(dname, dip->di_dname, DVNAMELEN - 1) == 0)
209: return(dip);
210:
211: dip++;
212: }
213:
214: panic("failed to find driverinfo entry for %s\n", dname);
215: /* NOTREACHED */
216:
217: return(NULL);
218: }
219:
220:
CVSweb