Return to kern_devconfig.c CVS log | Up to [local] / funnyos / kern |
1.1 init 1: /* 1.11 ! nbrk 2: * $Id: kern_devconfig.c,v 1.10 2007/12/16 12:54:44 nbrk 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) 1.9 nbrk 141: panic("failed to allocate space for %s devdata\n", aip->ai_cname); 1.1 init 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 */ 1.11 ! nbrk 180: if (drp->dr_interrupt != NULL && aip->ai_intrno != -1) { 1.8 init 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: