void __init setup_arch(char **cmdline_p) { unsigned long bootmap_size; unsigned long start_pfn, max_pfn, max_low_pfn; #ifdef CONFIG_EARLY_PRINTK extern void enable_early_printk(void); enable_early_printk(); #endif #ifdef CONFIG_CMDLINE_BOOL strcpy(COMMAND_LINE, CONFIG_CMDLINE); #endif ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV); #ifdef CONFIG_BLK_DEV_RAM rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK; rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0); rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0); #endif if (!MOUNT_ROOT_RDONLY) root_mountflags &= ~MS_RDONLY; init_mm.start_code = (unsigned long) _text; init_mm.end_code = (unsigned long) _etext; init_mm.end_data = (unsigned long) _edata; init_mm.brk = (unsigned long) _end; code_resource.start = virt_to_bus(_text); code_resource.end = virt_to_bus(_etext)-1; data_resource.start = virt_to_bus(_etext); data_resource.end = virt_to_bus(_edata)-1; sh_mv_setup(cmdline_p); #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) #define PFN_DOWN(x) ((x) >> PAGE_SHIFT) #define PFN_PHYS(x) ((x) << PAGE_SHIFT) #ifdef CONFIG_DISCONTIGMEM NODE_DATA(0)->bdata = &discontig_node_bdata[0]; NODE_DATA(1)->bdata = &discontig_node_bdata[1]; bootmap_size = init_bootmem_node(NODE_DATA(1), PFN_UP(__MEMORY_START_2ND), PFN_UP(__MEMORY_START_2ND), PFN_DOWN(__MEMORY_START_2ND+__MEMORY_SIZE_2ND)); free_bootmem_node(NODE_DATA(1), __MEMORY_START_2ND, __MEMORY_SIZE_2ND); reserve_bootmem_node(NODE_DATA(1), __MEMORY_START_2ND, bootmap_size); #endif /* * Find the highest page frame number we have available */ max_pfn = PFN_DOWN(__pa(memory_end)); /* * Determine low and high memory ranges: */ max_low_pfn = max_pfn; /* * Partially used pages are not usable - thus * we are rounding upwards: */ start_pfn = PFN_UP(__pa(_end)); /* * Find a proper area for the bootmem bitmap. After this * bootstrap step all allocations (until the page allocator * is intact) must be done via bootmem_alloc(). */ bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn, __MEMORY_START>>PAGE_SHIFT, max_low_pfn); /* * Register fully available low RAM pages with the bootmem allocator. */ { unsigned long curr_pfn, last_pfn, pages; /* * We are rounding up the start address of usable memory: */ curr_pfn = PFN_UP(__MEMORY_START); /* * ... and at the end of the usable range downwards: */ last_pfn = PFN_DOWN(__pa(memory_end)); if (last_pfn > max_low_pfn) last_pfn = max_low_pfn; pages = last_pfn - curr_pfn; free_bootmem_node(NODE_DATA(0), PFN_PHYS(curr_pfn), PFN_PHYS(pages)); } /* * Reserve the kernel text and * Reserve the bootmem bitmap. We do this in two steps (first step * was init_bootmem()), because this catches the (definitely buggy) * case of us accidentally initializing the bootmem allocator with * an invalid RAM area. */ reserve_bootmem_node(NODE_DATA(0), __MEMORY_START+PAGE_SIZE, (PFN_PHYS(start_pfn)+bootmap_size+PAGE_SIZE-1)-__MEMORY_START); /* * reserve physical page 0 - it's a special BIOS page on many boxes, * enabling clean reboots, SMP operation, laptop functions. */ reserve_bootmem_node(NODE_DATA(0), __MEMORY_START, PAGE_SIZE); #ifdef CONFIG_BLK_DEV_INITRD ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); if (&__rd_start != &__rd_end) { LOADER_TYPE = 1; INITRD_START = PHYSADDR((unsigned long)&__rd_start) - __MEMORY_START; INITRD_SIZE = (unsigned long)&__rd_end - (unsigned long)&__rd_start; } if (LOADER_TYPE && INITRD_START) { if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) { reserve_bootmem_node(NODE_DATA(0), INITRD_START+__MEMORY_START, INITRD_SIZE); initrd_start = INITRD_START ? INITRD_START + PAGE_OFFSET + __MEMORY_START : 0; initrd_end = initrd_start + INITRD_SIZE; } else { printk("initrd extends beyond end of memory " "(0x%08lx > 0x%08lx)\ndisabling initrd\n", INITRD_START + INITRD_SIZE, max_low_pfn << PAGE_SHIFT); initrd_start = 0; } } #endif #ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; #endif /* Perform the machine specific initialisation */ platform_setup(); paging_init(); }
static void __exit mod_exit(void) { struct list_head *u; struct list_head *unext; struct list_head *registeredlistp; struct registered_user *user; int found_user; int i; #ifdef USE_CLASS_SIMPLE class_simple_device_remove(MKDEV(major, 0)); class_simple_destroy(dma_class); #else #ifdef USE_CLASS_DEVICE class_device_destroy(dma_class, MKDEV(major, 0)); #else device_destroy(dma_class, MKDEV(major, 0)); #endif // USE_CLASS_DEVICE class_destroy(dma_class); #endif // USE_CLASS_SIMPLE unregister_chrdev(major, "edma"); /* * Free all "owned" channels now. They're supposed to get either * explicitly freed, or auto-freed when the file descriptor for * this device driver is closed by a process (which itself might happen * during auto-close if the process doesn't explicitly close the file * descriptor), but a process might crash or otherwise not get to the * auto-close point. The following code will run when the module is * removed from the kernel (w/ rmmod). */ for (i = 0; i < NCHAN; i++) { found_user = 0; if (mutex_lock_interruptible(&edma_mutex)) { return; } registeredlistp = &channels[i].users; u = registeredlistp->next; while (u != registeredlistp) { found_user = 1; unext = u->next; user = list_entry(u, struct registered_user, element); list_del(u); kfree(user); u = unext; } if (found_user) { release_channel(i); } mutex_unlock(&edma_mutex); } __D("edma unregistered\n"); }
/* * device_setup_cdev - setup cdev and device for habanalabs device * * @hdev: pointer to habanalabs device structure * @hclass: pointer to the class object of the device * @minor: minor number of the specific device * @fpos : file operations to install for this device * * Create a cdev and a Linux device for habanalabs's device. Need to be * called at the end of the habanalabs device initialization process, * because this function exposes the device to the user */ static int device_setup_cdev(struct hl_device *hdev, struct class *hclass, int minor, const struct file_operations *fops) { int err, devno = MKDEV(hdev->major, minor); struct cdev *hdev_cdev = &hdev->cdev; char *name; name = kasprintf(GFP_KERNEL, "hl%d", hdev->id); if (!name) return -ENOMEM; cdev_init(hdev_cdev, fops); hdev_cdev->owner = THIS_MODULE; err = cdev_add(hdev_cdev, devno, 1); if (err) { pr_err("Failed to add char device %s\n", name); goto err_cdev_add; }
static void uio_major_cleanup(void) { unregister_chrdev_region(MKDEV(uio_major, 0), UIO_MAX_DEVICES); cdev_del(uio_cdev); }
/* * 模块加载方法 */ static ini __init hello_init(void){ int err = -1; dev_t dev = 0; struct device* temp = NULL; printk(KERN_ALERT"Initializing hello device.\n"); /* * 动态分配主设备号和从设备号 */ err = alloc_chrdev_region(&dev, 0, 1, HELLO_DEVICE_NODE_NAME); if(err < 0){ printk(KERN_ALERT"Failed to alloc char dev region.\n"); goto fail; } hello_major = MAJOR(dev); hello_minor = MINOR(dev); /* * 分配hello设备结构体变量 */ hello_dev = kmalloc(sizeof(struct hello_android_dev), GFP_KERNEL); if(!hello_dev){ err = -ENOMEM; printk(KERN_ALERT"Failed to alloc hello_dev.\n"); goto unregister; } /* * 初始化设备 */ err = __hello_setup_dev(hello_dev); if(err){ printk(KERN_ALERT"Failed to setup dev:%d.\n", err); goto cleanup; } /* * 在/sys/class/目录下创建设备类别目录hello */ hello_class = class_create(THIS_MODULE, HELLO_DEVICE_CLASS_NAME); if(IS_ERR(hello_class)){ err = PTR_ERR(hello_class); printk(KERN_ALERT"Failed to create hello class.\n"); goto destroy_cdev; } /* * 在/dev/目录和/sys/class/hello目录下分别创建设备文件hello */ temp = device_create(hello_class, NULL, dev, "%s", HELLO_DEVICE_FILE_NAME); if(IS_ERR(temp)){ err = PRT_ERR(temp); printk(KERN_ALERT"Failed to create hello device.\n"); goto destroy_class; } /* * 在/sys/class/hello/hello目录下创建属性文件val */ err = device_create_file(temp, &dev_attr_val); if(err < 0){ printk(KERN_ALERT"Failed to create attribute val.\n"); goto destroy_device; } dev_set_drvdata(temp, hello_dev); /* * 创建/proc/hello文件 */ hello_create_proc(); printk(KERN_ALERT"Successed to initalize hello device.\n"); return 0; destroy_device: device_destroy(hello_class, dev); destroy_class: class_destroy(hello_class); destroy_cdev: cdev_del(&(hello_dev->dev)); cleanup: kfree(hello_dev); unregister: unregister_chrdev_region(MKDEV(hello_major, hello_minor), 1); fail: return err; }
void timed_output_dev_unregister(struct timed_output_dev *tdev) { device_remove_file(tdev->dev, &dev_attr_enable); dev_set_drvdata(tdev->dev, NULL); device_destroy(timed_output_class, MKDEV(0, tdev->index)); }
static int __init rtlx_module_init(void) { struct device *dev; int i, err; if (!cpu_has_mipsmt) { printk("VPE loader: not a MIPS MT capable processor\n"); return -ENODEV; } if (tclimit == 0) { printk(KERN_WARNING "No TCs reserved for AP/SP, not " "initializing RTLX.\nPass maxtcs=<n> argument as kernel " "argument\n"); return -ENODEV; } major = register_chrdev(0, module_name, &rtlx_fops); if (major < 0) { printk(register_chrdev_failed); return major; } /* initialise the wait queues */ for (i = 0; i < RTLX_CHANNELS; i++) { init_waitqueue_head(&channel_wqs[i].rt_queue); init_waitqueue_head(&channel_wqs[i].lx_queue); atomic_set(&channel_wqs[i].in_open, 0); mutex_init(&channel_wqs[i].mutex); dev = device_create(mt_class, NULL, MKDEV(major, i), NULL, "%s%d", module_name, i); if (IS_ERR(dev)) { err = PTR_ERR(dev); goto out_chrdev; } } /* set up notifiers */ notify.start = starting; notify.stop = stopping; vpe_notify(tclimit, ¬ify); if (cpu_has_vint) set_vi_handler(MIPS_CPU_RTLX_IRQ, rtlx_dispatch); else { pr_err("APRP RTLX init on non-vectored-interrupt processor\n"); err = -ENODEV; goto out_chrdev; } rtlx_irq.dev_id = rtlx; setup_irq(rtlx_irq_num, &rtlx_irq); return 0; out_chrdev: for (i = 0; i < RTLX_CHANNELS; i++) device_destroy(mt_class, MKDEV(major, i)); return err; }
dev_t name_to_dev_t(char *name) { char s[32]; char *p; dev_t res = 0; int part; #ifdef CONFIG_BLOCK if (strncmp(name, "PARTUUID=", 9) == 0) { name += 9; if (strlen(name) != 36) goto fail; res = devt_from_partuuid(name); if (!res) goto fail; goto done; } #endif if (strncmp(name, "/dev/", 5) != 0) { unsigned maj, min; if (sscanf(name, "%u:%u", &maj, &min) == 2) { res = MKDEV(maj, min); if (maj != MAJOR(res) || min != MINOR(res)) goto fail; } else { res = new_decode_dev(simple_strtoul(name, &p, 16)); if (*p) goto fail; } goto done; } name += 5; res = Root_NFS; if (strcmp(name, "nfs") == 0) goto done; res = Root_RAM0; if (strcmp(name, "ram") == 0) goto done; if (strlen(name) > 31) goto fail; strcpy(s, name); for (p = s; *p; p++) if (*p == '/') *p = '!'; res = blk_lookup_devt(s, 0); if (res) goto done; /* * try non-existent, but valid partition, which may only exist * after revalidating the disk, like partitioned md devices */ while (p > s && isdigit(p[-1])) p--; if (p == s || !*p || *p == '0') goto fail; /* try disk name without <part number> */ part = simple_strtoul(p, NULL, 10); *p = '\0'; res = blk_lookup_devt(s, part); if (res) goto done; /* try disk name without p<part number> */ if (p < s + 2 || !isdigit(p[-2]) || p[-1] != 'p') goto fail; p[-1] = '\0'; res = blk_lookup_devt(s, part); if (res) goto done; fail: return 0; done: return res; }
static int __init init_function(void) { int ret,l; #ifdef DEBUG printk(KERN_INFO "Begin: %s\n",__func__); #endif quantum = QUANTUMSIZ; qset = QSETSIZ; size = DEVICESIZ; minor_no = MINOR_NO; // scull.c_dev.owner = THIS_MODULE; // scull.c_dev.ops = &fops; nod = NOD; ret = alloc_chrdev_region(&devno,minor_no,NOD,DEV_NAME); // if i give minor no 0 here thn alloc_chrdev_region will register only for minor_no 0 ?????? if(ret < 0) { #ifdef DEBUG printk(KERN_ALERT "alloc_chrdev_region() fails\n"); #endif return ret; } temp_devno = devno; major_no = MAJOR(temp_devno); for(l = 0;l< NOD; l++) { temp_devno = MKDEV(major_no,minor_no + l); //devno changed here which is causing trouble in unregistre_chrdev_region due to which allocated devno device is not unregisterd????????? dev[l] = (struct scull_dev *)kmalloc(sizeof(struct scull_dev),GFP_KERNEL); memset(dev[l],'\0',sizeof(struct scull_dev)); dev[l]->quantum = quantum; dev[l]->qset = qset; dev[l]->size = size; dev[l]->c_dev.owner = THIS_MODULE; dev[l]->c_dev.ops = &fops; dev[l]->c_dev.dev = temp_devno; dev[l]->c_dev.count = nod; //major_no = MAJOR(devno); //minor_no = MINOR(devno); if(check_region(0x378,3) < 0) { release_region(0x378,3); } if(request_region(0x378,3,"MYPP") == NULL) { #ifdef DEBUG printk(KERN_INFO "requset_region fails\n"); #endif return -1; } cdev_init(&dev[l]->c_dev,&fops); sema_init(&dev[l]->sem,1); ret = cdev_add(&dev[l]->c_dev,temp_devno,nod); if(ret <= -1){ #ifdef DEBUG printk(KERN_ERR "cdev_add() fails\n"); #endif return ret; } #ifdef DEBUG printk(KERN_INFO "major_no: %d minor_no: %d\n",MAJOR(temp_devno),MINOR(temp_devno)); #endif } //minor_no = 1; #ifdef DEBUG printk(KERN_INFO "End: %s\n",__func__); #endif return 0; }
static dev_t try_name(char *name, int part) { char path[64]; char buf[32]; int range; dev_t res; char *s; int len; int fd; unsigned int maj, min; /* read device number from .../dev */ sprintf(path, "/sys/block/%s/dev", name); fd = sys_open(path, 0, 0); if (fd < 0) goto fail; len = sys_read(fd, buf, 32); sys_close(fd); if (len <= 0 || len == 32 || buf[len - 1] != '\n') goto fail; buf[len - 1] = '\0'; if (sscanf(buf, "%u:%u", &maj, &min) == 2) { /* * Try the %u:%u format -- see print_dev_t() */ res = MKDEV(maj, min); if (maj != MAJOR(res) || min != MINOR(res)) goto fail; } else { /* * Nope. Try old-style "0321" */ res = new_decode_dev(simple_strtoul(buf, &s, 16)); if (*s) goto fail; } /* if it's there and we are not looking for a partition - that's it */ if (!part) return res; /* otherwise read range from .../range */ sprintf(path, "/sys/block/%s/range", name); fd = sys_open(path, 0, 0); if (fd < 0) goto fail; len = sys_read(fd, buf, 32); sys_close(fd); if (len <= 0 || len == 32 || buf[len - 1] != '\n') goto fail; buf[len - 1] = '\0'; range = simple_strtoul(buf, &s, 10); if (*s) goto fail; /* if partition is within range - we got it */ if (part < range) return res + part; fail: return 0; }
#define MTK_MJC_DEV_MAJOR_NUMBER 168 #define MJC_FORCE_REG_NUM 100 #define EFUSE_MJC_IDX (3) #define EFUSE_MJC_BIT (1<<16) //**************************************************// // variable //**************************************************// static DEFINE_SPINLOCK(ContextLock); static DEFINE_SPINLOCK(HWLock); static MJC_CONTEXT_T grContext; //spinlock : ContextLock static MJC_CONTEXT_T grHWLockContext; //spinlock : HWLock static dev_t mjc_devno = MKDEV(MTK_MJC_DEV_MAJOR_NUMBER,0); static struct cdev *g_mjc_cdev; static struct class *pMjcClass = NULL; static struct device* mjcDevice = NULL; unsigned long gulRegister, gu1PaReg, gu1PaSize; int gi4IrqID; MJC_WRITE_REG_T gfWriteReg[MJC_FORCE_REG_NUM]; /***************************************************************************** * FUNCTION * _mjc_CreateEvent * DESCRIPTION * * PARAMETERS * None.
dev_t name_to_dev_t(char *name) { char s[32]; char *p; dev_t res = 0; int part; #ifdef CONFIG_SYSFS int mkdir_err = sys_mkdir("/sys", 0700); if (sys_mount("sysfs", "/sys", "sysfs", 0, NULL) < 0) goto out; #endif if (strncmp(name, "/dev/", 5) != 0) { unsigned maj, min; if (sscanf(name, "%u:%u", &maj, &min) == 2) { res = MKDEV(maj, min); if (maj != MAJOR(res) || min != MINOR(res)) goto fail; } else { res = new_decode_dev(simple_strtoul(name, &p, 16)); if (*p) goto fail; } goto done; } name += 5; res = Root_NFS; if (strcmp(name, "nfs") == 0) goto done; res = Root_RAM0; if (strcmp(name, "ram") == 0) goto done; if (strlen(name) > 31) goto fail; strcpy(s, name); for (p = s; *p; p++) if (*p == '/') *p = '!'; res = try_name(s, 0); if (res) goto done; while (p > s && isdigit(p[-1])) p--; if (p == s || !*p || *p == '0') goto fail; part = simple_strtoul(p, NULL, 10); *p = '\0'; res = try_name(s, part); if (res) goto done; if (p < s + 2 || !isdigit(p[-2]) || p[-1] != 'p') goto fail; p[-1] = '\0'; res = try_name(s, part); done: #ifdef CONFIG_SYSFS sys_umount("/sys", 0); out: if (!mkdir_err) sys_rmdir("/sys"); #endif return res; fail: res = 0; goto done; }
/*---------------------------------------------------------- * pipe_init *---------------------------------------------------------*/ static int pipe_init(void) { dev_t dev = MKDEV(pipe_major, 0); int alloc_ret = 0; int cdev_err = 0; struct device *class_dev = NULL; /* * register major number */ /* reserve major number */ if (pipe_major) { alloc_ret = register_chrdev_region(dev, pipe_dev_count, DRIVER_NAME); if (alloc_ret < 0) { printk(KERN_ERR "pipe: unable to get major %d\n", pipe_major); goto error; } if (pipe_major == 0) pipe_major = alloc_ret; } else { alloc_ret = alloc_chrdev_region(&dev, pipe_minor, pipe_dev_count, DRIVER_NAME); if (alloc_ret) { printk(KERN_ERR "pipe: unable to get major \n"); goto error; } pipe_major = MAJOR(dev); } /* register system call handler(fops) */ cdev_init(&pipe_cdev, &pipe_ops); /* register to kernel */ pipe_cdev.owner = THIS_MODULE; pipe_cdev.ops = &pipe_ops; cdev_err = cdev_add (&pipe_cdev, MKDEV(pipe_major, pipe_minor), pipe_dev_count); if (cdev_err) { goto error; } /* register class */ pipe_class = class_create(THIS_MODULE, DRIVER_NAME); if (IS_ERR(pipe_class)) { goto error; } class_dev = device_create(pipe_class, NULL, MKDEV(pipe_major, pipe_minor), NULL, DRIVER_NAME); if (IS_ERR(class_dev)) printk(KERN_ERR "pipe: can't create device\n"); return 0; error: if (cdev_err == 0) cdev_del(&pipe_cdev); if (alloc_ret == 0) unregister_chrdev_region(MKDEV(pipe_major, 0), pipe_dev_count); return -1; }
#define SENSOR_LOG_DEBUG(fmt, args...) printk(KERN_DEBUG "[%s] [%s: %d] " fmt,\ LOG_TAG,__FUNCTION__, __LINE__, ##args) #else #define SENSOR_LOG_INFO(fmt, args...) #define SENSOR_LOG_DEBUG(fmt, args...) #endif #else #define SENSOR_LOG_ERROR(fmt, args...) #define SENSOR_LOG_INFO(fmt, args...) #define SENSOR_LOG_DEBUG(fmt, args...) #endif static dev_t const hall_device_dev_t = MKDEV(MISC_MAJOR, 252); static struct class *hall_device_class; static const struct dev_pm_ops hall_device_pm_ops = { .suspend = hall_device_suspend, .resume = hall_device_resume, }; static const struct i2c_device_id hall_device_idtable_id[] = { { "zte,hall_pair_out", 0 }, { }, }; static struct of_device_id of_hall_device_idtable[] = { { .compatible = "zte,hall_pair_out",},
/*! * This function is called by the driver framework to initialize the LDB * device. * * @param dev The device structure for the LDB passed in by the * driver framework. * * @return Returns 0 on success or negative error code on error */ static int ldb_probe(struct platform_device *pdev) { int ret = 0; struct resource *res; struct ldb_platform_data *plat_data = pdev->dev.platform_data; uint32_t reg; struct device *temp; int mxc_ldb_major; struct class *mxc_ldb_class; if ((plat_data->boot_enable & (MXC_LDBDI0 | MXC_LDBDI1)) && !g_enable_ldb) { g_enable_ldb = MXC_ENABLE; if (plat_data->boot_enable & MXC_LDBDI0) g_di0_used = true; if (plat_data->boot_enable & MXC_LDBDI1) g_di1_used = true; } if (!g_enable_ldb) g_enable_ldb = MXC_DISABLE; if (g_enable_ldb == MXC_DISABLE) { printk(KERN_WARNING "By setting, LDB driver will not be enabled\n"); return -ENODEV; } spin_lock_init(&ldb_lock); g_ldb_dev = &pdev->dev; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (IS_ERR(res)) return -ENODEV; memset(&ldb, 0, sizeof(struct ldb_data)); ldb.chan_mode_opt = g_chan_mode_opt; ldb.chan_bit_map[0] = g_chan_bit_map[0]; ldb.chan_bit_map[1] = g_chan_bit_map[1]; ldb.base_addr = res->start; ldb_reg = ioremap(ldb.base_addr, res->end - res->start + 1); ldb.control_reg = ldb_reg + 2; ldb.bgref_rmode = plat_data->ext_ref; ldb.lvds_bg_reg = regulator_get(&pdev->dev, plat_data->lvds_bg_reg); if (!IS_ERR(ldb.lvds_bg_reg)) { regulator_set_voltage(ldb.lvds_bg_reg, 2500000, 2500000); regulator_enable(ldb.lvds_bg_reg); } reg = __raw_readl(ldb.control_reg); if (ldb.bgref_rmode == LDB_EXT_REF) __raw_writel((reg & ~LDB_BGREF_RMODE_MASK) | LDB_BGREF_RMODE_EXT, ldb.control_reg); else __raw_writel((reg & ~LDB_BGREF_RMODE_MASK) | LDB_BGREF_RMODE_INT, ldb.control_reg); mxc_ldb_major = register_chrdev(0, "mxc_ldb", &mxc_ldb_fops); if (mxc_ldb_major < 0) { dev_err(g_ldb_dev, "Unable to register MXC LDB as a char " "device\n"); ret = mxc_ldb_major; goto err0; } mxc_ldb_class = class_create(THIS_MODULE, "mxc_ldb"); if (IS_ERR(mxc_ldb_class)) { dev_err(g_ldb_dev, "Unable to create class for MXC LDB\n"); ret = PTR_ERR(mxc_ldb_class); goto err1; } temp = device_create(mxc_ldb_class, NULL, MKDEV(mxc_ldb_major, 0), NULL, "mxc_ldb"); if (IS_ERR(temp)) { dev_err(g_ldb_dev, "Unable to create class device for " "MXC LDB\n"); ret = PTR_ERR(temp); goto err2; } if (g_di0_used) { mxcfb_register_mode(0, mxcfb_ldb_modedb, mxcfb_ldb_modedb_sz, MXC_DISP_SPEC_DEV); mxcfb_register_presetup(0, ldb_fb_pre_setup); } if (g_di1_used) { mxcfb_register_mode(1, mxcfb_ldb_modedb, mxcfb_ldb_modedb_sz, MXC_DISP_SPEC_DEV); mxcfb_register_presetup(1, ldb_fb_pre_setup); } ret = fb_register_client(&nb); if (ret < 0) goto err2; ldb.blank[0] = ldb.blank[1] = -1; return ret; err2: class_destroy(mxc_ldb_class); err1: unregister_chrdev(mxc_ldb_major, "mxc_ldb"); err0: iounmap(ldb_reg); return ret; }
static int WIFI_init(void) { dev_t dev = MKDEV(WIFI_major, 0); INT32 alloc_ret = 0; INT32 cdev_err = 0; #if WMT_CREATE_NODE_DYNAMIC struct device * wmtwifi_dev = NULL; #endif /* static allocate chrdev */ alloc_ret = register_chrdev_region(dev, 1, WIFI_DRIVER_NAME); if (alloc_ret) { WIFI_ERR_FUNC("Fail to register chrdev\n"); return alloc_ret; } cdev_init(&WIFI_cdev, &WIFI_fops); WIFI_cdev.owner = THIS_MODULE; cdev_err = cdev_add(&WIFI_cdev, dev, WIFI_devs); if (cdev_err) { goto error; } #if WMT_CREATE_NODE_DYNAMIC //mknod replace wmtwifi_class = class_create(THIS_MODULE,"wmtWifi"); if(IS_ERR(wmtwifi_class)) goto error; wmtwifi_dev = device_create(wmtwifi_class,NULL,dev,NULL,"wmtWifi"); if(IS_ERR(wmtwifi_dev)) goto error; #endif sema_init(&wr_mtx, 1); WIFI_INFO_FUNC("%s driver(major %d) installed.\n", WIFI_DRIVER_NAME, WIFI_major); retflag = 0; wlan_mode = WLAN_MODE_HALT; pf_set_p2p_mode = NULL; return 0; error: #if WMT_CREATE_NODE_DYNAMIC if(!IS_ERR(wmtwifi_dev)) device_destroy(wmtwifi_class,dev); if(!IS_ERR(wmtwifi_class)){ class_destroy(wmtwifi_class); wmtwifi_class = NULL; } #endif if (cdev_err == 0) { cdev_del(&WIFI_cdev); } if (alloc_ret == 0) { unregister_chrdev_region(dev, WIFI_devs); } return -1; }
\************************************************************************/ #include <linux/interrupt.h> #include <linux/version.h> #include <linux/ioport.h> #include <linux/module.h> #include <linux/sched.h> #include <linux/cdev.h> #include <linux/fs.h> #include <asm/uaccess.h> #include <asm/io.h> static char * nom_module = "exemple_13_B"; static dev_t dev_exemple = MKDEV(0, 0); static int numero = 0; module_param(numero, int, 0644); static int irq_number = 1; module_param(irq_number, int, 0444); static struct cdev cdev_exemple; static int read_exemple (struct file * filp, char * buffer, size_t length, loff_t * offset); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) static irqreturn_t irq_handler(int irq, void * ident, struct pt_regs * unused); #else
static void __init unix98_pty_init(void) { ptm_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX); if (!ptm_driver) panic("Couldn't allocate Unix98 ptm driver"); pts_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX); if (!pts_driver) panic("Couldn't allocate Unix98 pts driver"); ptm_driver->owner = THIS_MODULE; ptm_driver->driver_name = "pty_master"; ptm_driver->name = "ptm"; ptm_driver->major = UNIX98_PTY_MASTER_MAJOR; ptm_driver->minor_start = 0; ptm_driver->type = TTY_DRIVER_TYPE_PTY; ptm_driver->subtype = PTY_TYPE_MASTER; ptm_driver->init_termios = tty_std_termios; ptm_driver->init_termios.c_iflag = 0; ptm_driver->init_termios.c_oflag = 0; ptm_driver->init_termios.c_cflag = B38400 | CS8 | CREAD; ptm_driver->init_termios.c_lflag = 0; ptm_driver->init_termios.c_ispeed = 38400; ptm_driver->init_termios.c_ospeed = 38400; ptm_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM; ptm_driver->other = pts_driver; tty_set_operations(ptm_driver, &ptm_unix98_ops); pts_driver->owner = THIS_MODULE; pts_driver->driver_name = "pty_slave"; pts_driver->name = "pts"; pts_driver->major = UNIX98_PTY_SLAVE_MAJOR; pts_driver->minor_start = 0; pts_driver->type = TTY_DRIVER_TYPE_PTY; pts_driver->subtype = PTY_TYPE_SLAVE; pts_driver->init_termios = tty_std_termios; pts_driver->init_termios.c_cflag = B38400 | CS8 | CREAD; pts_driver->init_termios.c_ispeed = 38400; pts_driver->init_termios.c_ospeed = 38400; pts_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM; pts_driver->other = ptm_driver; tty_set_operations(pts_driver, &pty_unix98_ops); if (tty_register_driver(ptm_driver)) panic("Couldn't register Unix98 ptm driver"); if (tty_register_driver(pts_driver)) panic("Couldn't register Unix98 pts driver"); register_sysctl_table(pty_root_table); /* Now create the /dev/ptmx special device */ tty_default_fops(&ptmx_fops); ptmx_fops.open = ptmx_open; cdev_init(&ptmx_cdev, &ptmx_fops); if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) || register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0) panic("Couldn't register /dev/ptmx driver\n"); device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx"); }
void __init prom_init(void) { char *ptr; cfe_init(cfe_handle, cfe_entry); bchip_check_compat(); board_pinmux_setup(); bchip_mips_setup(); set_board_nmi_handler(); /* default to SATA (where available) or MTD rootfs */ #ifdef CONFIG_BRCM_HAS_SATA ROOT_DEV = Root_SDA1; #else ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, 0); #endif root_mountflags &= ~MS_RDONLY; bchip_set_features(); #if defined(CONFIG_BRCM_IKOS_DEBUG) strcpy(arcs_cmdline, "debug initcall_debug"); #elif !defined(CONFIG_BRCM_IKOS) cfe_read_configuration(); #endif brcm_setup_early_printk(); #ifdef CONFIG_CMDLINE_BOOL #ifdef CONFIG_CMDLINE_OVERRIDE strlcpy(arcs_cmdline, builtin_cmdline, COMMAND_LINE_SIZE); #else if (builtin_cmdline[0]) { strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE); strlcat(arcs_cmdline, builtin_cmdline, COMMAND_LINE_SIZE); } #endif #endif /* provide "ubiroot" alias to reduce typing */ if (strstr(arcs_cmdline, "ubiroot")) strcat(arcs_cmdline, " ubi.mtd=rootfs rootfstype=ubifs " "root=ubi0:rootfs"); ptr = strstr(arcs_cmdline, "memc1="); if (ptr) brcm_dram1_linux_mb = memparse(ptr + 6, &ptr) >> 20; printk(KERN_INFO "Options: enet_en=%d enet0_mii=%d enet_no_mdio=%d " "enet1_en=%d moca=%d\n", brcm_enet_enabled, brcm_enet0_force_ext_mii, brcm_enet_no_mdio, brcm_enet1_enabled, brcm_moca_enabled); printk(KERN_INFO " sata=%d docsis=%d pci=%d pcie=%d smp=%d " "usb=%d\n", brcm_sata_enabled, brcm_docsis_platform, brcm_pci_enabled, brcm_pcie_enabled, brcm_smp_enabled, brcm_usb_enabled); bchip_early_setup(); board_get_ram_size(&brcm_dram0_size_mb, &brcm_dram1_size_mb); do { unsigned long dram0_mb = brcm_dram0_size_mb, mb; mb = min(dram0_mb, BRCM_MAX_LOWER_MB); dram0_mb -= mb; add_memory_region(0, mb << 20, BOOT_MEM_RAM); if (!dram0_mb) break; #ifdef CONFIG_BRCM_UPPER_MEMORY mb = min(dram0_mb, BRCM_MAX_UPPER_MB); dram0_mb -= mb; brcm_upper_tlb_setup(); add_memory_region(UPPERMEM_START, mb << 20, BOOT_MEM_RAM); if (!dram0_mb) break; #endif #if defined(CONFIG_HIGHMEM) add_memory_region(HIGHMEM_START, dram0_mb << 20, BOOT_MEM_RAM); break; #endif /* * We wound up here because the chip's architecture cannot * make use of all MEMC0 RAM in Linux. i.e. no suitable * HIGHMEM or upper memory options are supported by the CPU. * * But we can still report the excess memory as a "bonus" * reserved (bmem) region, so the application can manage it. */ mb = brcm_dram0_size_mb - dram0_mb; /* Linux memory */ if (!brcm_dram1_size_mb && mb == 256) { printk(KERN_INFO "MEMC0 split: %lu MB -> Linux; " "%lu MB -> extra bmem\n", mb, dram0_mb); brcm_dram1_size_mb = dram0_mb; brcm_dram1_start = UPPERMEM_START; } } while (0); #if defined(CONFIG_HIGHMEM) && defined(CONFIG_BRCM_HAS_1GB_MEMC1) if (brcm_dram1_linux_mb > brcm_dram1_size_mb) { printk(KERN_WARNING "warning: 'memc1=%luM' exceeds " "available memory (%lu MB); ignoring\n", brcm_dram1_linux_mb, brcm_dram1_size_mb); brcm_dram1_linux_mb = 0; } else if (brcm_dram1_linux_mb) { /* Since the bootloader can only map the first 256M of memc1 * when it boots, if we get memc1= request from bootloader, we * should try to pull the memory from the end to avoid crossing * over the memory that is allocated for boot logo image by * bootloader. */ unsigned long start_mb, start_b, size, splash_bound = 0; if (0 == parse_splash_mem(arcs_cmdline, &splash_bound, &size)) { splash_bound += size; } start_mb = brcm_dram1_size_mb - brcm_dram1_linux_mb; start_b = start_mb << 20; if (splash_bound > start_b) { unsigned long orig_dram1 = brcm_dram1_linux_mb; start_mb = (splash_bound + 0x000FFFFF) >> 20; start_b = start_mb << 20; brcm_dram1_linux_mb = brcm_dram1_size_mb - start_mb; printk(KERN_WARNING "warning: 'memc1=%luM' starts " " before splash memory bound (0x%lx);" " adjusting to (memc1=%luM)\n", orig_dram1, splash_bound, brcm_dram1_linux_mb); } printk(KERN_INFO "memc1: adding %luMB at %luMB " "(0x%08lx@0x%08lx)", brcm_dram1_linux_mb, (MEMC1_START >> 20) + start_mb, brcm_dram1_linux_mb << 20, MEMC1_START + start_b); add_memory_region(MEMC1_START + start_b, brcm_dram1_linux_mb << 20, BOOT_MEM_RAM); }
static int __zvol_create_minor(const char *name, boolean_t ignore_snapdev) { zvol_state_t *zv; objset_t *os; dmu_object_info_t *doi; uint64_t volsize; uint64_t len; unsigned minor = 0; int error = 0; ASSERT(MUTEX_HELD(&zvol_state_lock)); zv = zvol_find_by_name(name); if (zv) { error = SET_ERROR(EEXIST); goto out; } if (ignore_snapdev == B_FALSE) { error = __zvol_snapdev_hidden(name); if (error) goto out; } doi = kmem_alloc(sizeof (dmu_object_info_t), KM_SLEEP); error = dmu_objset_own(name, DMU_OST_ZVOL, B_TRUE, zvol_tag, &os); if (error) goto out_doi; error = dmu_object_info(os, ZVOL_OBJ, doi); if (error) goto out_dmu_objset_disown; error = zap_lookup(os, ZVOL_ZAP_OBJ, "size", 8, 1, &volsize); if (error) goto out_dmu_objset_disown; error = zvol_find_minor(&minor); if (error) goto out_dmu_objset_disown; zv = zvol_alloc(MKDEV(zvol_major, minor), name); if (zv == NULL) { error = SET_ERROR(EAGAIN); goto out_dmu_objset_disown; } if (dmu_objset_is_snapshot(os)) zv->zv_flags |= ZVOL_RDONLY; zv->zv_volblocksize = doi->doi_data_block_size; zv->zv_volsize = volsize; zv->zv_objset = os; set_capacity(zv->zv_disk, zv->zv_volsize >> 9); blk_queue_max_hw_sectors(zv->zv_queue, (DMU_MAX_ACCESS / 4) >> 9); blk_queue_max_segments(zv->zv_queue, UINT16_MAX); blk_queue_max_segment_size(zv->zv_queue, UINT_MAX); blk_queue_physical_block_size(zv->zv_queue, zv->zv_volblocksize); blk_queue_io_opt(zv->zv_queue, zv->zv_volblocksize); blk_queue_max_discard_sectors(zv->zv_queue, (zvol_max_discard_blocks * zv->zv_volblocksize) >> 9); blk_queue_discard_granularity(zv->zv_queue, zv->zv_volblocksize); queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, zv->zv_queue); #ifdef QUEUE_FLAG_NONROT queue_flag_set_unlocked(QUEUE_FLAG_NONROT, zv->zv_queue); #endif #ifdef QUEUE_FLAG_ADD_RANDOM queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, zv->zv_queue); #endif if (spa_writeable(dmu_objset_spa(os))) { if (zil_replay_disable) zil_destroy(dmu_objset_zil(os), B_FALSE); else zil_replay(os, zv, zvol_replay_vector); } /* * When udev detects the addition of the device it will immediately * invoke blkid(8) to determine the type of content on the device. * Prefetching the blocks commonly scanned by blkid(8) will speed * up this process. */ len = MIN(MAX(zvol_prefetch_bytes, 0), SPA_MAXBLOCKSIZE); if (len > 0) { dmu_prefetch(os, ZVOL_OBJ, 0, 0, len, ZIO_PRIORITY_SYNC_READ); dmu_prefetch(os, ZVOL_OBJ, 0, volsize - len, len, ZIO_PRIORITY_SYNC_READ); } zv->zv_objset = NULL; out_dmu_objset_disown: dmu_objset_disown(os, zvol_tag); out_doi: kmem_free(doi, sizeof (dmu_object_info_t)); out: if (error == 0) { zvol_insert(zv); add_disk(zv->zv_disk); } return (SET_ERROR(error)); }
static int __init pc8736x_gpio_init(void) { int rc; dev_t devid; pdev = platform_device_alloc(DEVNAME, 0); if (!pdev) return -ENOMEM; rc = platform_device_add(pdev); if (rc) { rc = -ENODEV; goto undo_platform_dev_alloc; } dev_info(&pdev->dev, "NatSemi pc8736x GPIO Driver Initializing\n"); if (!pc8736x_superio_present()) { rc = -ENODEV; dev_err(&pdev->dev, "no device found\n"); goto undo_platform_dev_add; } pc8736x_gpio_ops.dev = &pdev->dev; __VERIFIER_assert(pc8736x_gpio_ops.dev == &pdev->dev); /* Verify that chip and it's GPIO unit are both enabled. My BIOS does this, so I take minimum action here */ rc = superio_inb(SIO_CF1); if (!(rc & 0x01)) { rc = -ENODEV; dev_err(&pdev->dev, "device not enabled\n"); goto undo_platform_dev_add; } device_select(SIO_GPIO_UNIT); if (!superio_inb(SIO_UNIT_ACT)) { rc = -ENODEV; dev_err(&pdev->dev, "GPIO unit not enabled\n"); goto undo_platform_dev_add; } /* read the GPIO unit base addr that chip responds to */ pc8736x_gpio_base = (superio_inb(SIO_BASE_HADDR) << 8 | superio_inb(SIO_BASE_LADDR)); if (!request_region(pc8736x_gpio_base, PC8736X_GPIO_RANGE, DEVNAME)) { rc = -ENODEV; dev_err(&pdev->dev, "GPIO ioport %x busy\n", pc8736x_gpio_base); goto undo_platform_dev_add; } dev_info(&pdev->dev, "GPIO ioport %x reserved\n", pc8736x_gpio_base); if (major) { devid = MKDEV(major, 0); rc = register_chrdev_region(devid, PC8736X_GPIO_CT, DEVNAME); } else { rc = alloc_chrdev_region(&devid, 0, PC8736X_GPIO_CT, DEVNAME); major = MAJOR(devid); } if (rc < 0) { dev_err(&pdev->dev, "register-chrdev failed: %d\n", rc); goto undo_request_region; } if (!major) { major = rc; dev_dbg(&pdev->dev, "got dynamic major %d\n", major); } pc8736x_init_shadow(); /* ignore minor errs, and succeed */ cdev_init(&pc8736x_gpio_cdev, &pc8736x_gpio_fileops); cdev_add(&pc8736x_gpio_cdev, devid, PC8736X_GPIO_CT); return 0; undo_request_region: release_region(pc8736x_gpio_base, PC8736X_GPIO_RANGE); undo_platform_dev_add: platform_device_del(pdev); undo_platform_dev_alloc: platform_device_put(pdev); return rc; }
static int __init initfunc(void) { int ret1; int minorno; dev_t devno; int ret2; minorno=MINORNO; #ifdef DEBUG printk(KERN_ALERT"Hello Kernel \n"); #endif ret1=alloc_chrdev_region(&devid,minorno,1,DEVNAME); if(ret1<0) { #ifdef DEBUG printk(KERN_ERR"Error : alloc_chrdev_region failed!! \n"); goto OUT; #endif } #ifdef DEBUG printk(KERN_ALERT"Registration Successful!! \n"); #endif dev=kmalloc(sizeof(struct Dev),GFP_KERNEL); if(!dev) { #ifdef DEBUG printk(KERN_ERR"Error : kmalloc failed!! \n"); goto OUT; #endif } memset(dev,'\0',sizeof(struct Dev)); #ifdef DEBUG printk(KERN_ALERT"Memory Allocation Successful!! \n"); #endif device_initialization(); devno = MKDEV(MAJOR(devid),0); cdev_init(&dev->c_dev,&fops); dev->c_dev.owner = THIS_MODULE; dev->c_dev.ops = &fops; ret2=cdev_add(&dev->c_dev,devno,1); if(ret2<0) { #ifdef DEBUG printk(KERN_ERR"Error : cdev_add failed!! \n"); goto OUT; #endif } #ifdef DEBUG printk(KERN_ALERT"(Major = %d,Minor = %d)",MAJOR(devno),MINOR(devno)); #endif if( check_region(BASE,8) < 8 ) { #ifdef DEBUG printk(KERN_ALERT"Releasing resources!! \n"); #endif release_region(BASE,8); } if( !request_region(BASE,8,DEVNAME) ) { #ifdef DEBUG printk(KERN_ERR"Error : request_region failed!! \n"); goto OUT; #endif } return 0; OUT: return -1; }
/** * uio_register_device - register a new userspace IO device * @owner: module that creates the new device * @parent: parent device * @info: UIO device capabilities * * returns zero on success or a negative error code. */ int __uio_register_device(struct module *owner, struct device *parent, struct uio_info *info) { struct uio_device *idev; int ret = 0; if (!parent || !info || !info->name || !info->version) return -EINVAL; info->uio_dev = NULL; idev = kzalloc(sizeof(*idev), GFP_KERNEL); if (!idev) { ret = -ENOMEM; goto err_kzalloc; } idev->owner = owner; idev->info = info; init_waitqueue_head(&idev->wait); atomic_set(&idev->event, 0); ret = uio_get_minor(idev); if (ret) goto err_get_minor; idev->dev = device_create(&uio_class, parent, MKDEV(uio_major, idev->minor), idev, "uio%d", idev->minor); if (IS_ERR(idev->dev)) { printk(KERN_ERR "UIO: device register failed\n"); ret = PTR_ERR(idev->dev); goto err_device_create; } ret = uio_dev_add_attributes(idev); if (ret) goto err_uio_dev_add_attributes; info->uio_dev = idev; if (info->irq && (info->irq != UIO_IRQ_CUSTOM)) { ret = request_irq(info->irq, uio_interrupt, info->irq_flags, info->name, idev); if (ret) goto err_request_irq; } return 0; err_request_irq: uio_dev_del_attributes(idev); err_uio_dev_add_attributes: device_destroy(&uio_class, MKDEV(uio_major, idev->minor)); err_device_create: uio_free_minor(idev); err_get_minor: kfree(idev); err_kzalloc: return ret; }
static int __devinit chd_dec_init_chdev(struct crystalhd_adp *adp) { crystalhd_ioctl_data *temp; struct device *dev; int rc = -ENODEV, i = 0; if (!adp) goto fail; adp->chd_dec_major = register_chrdev(0, CRYSTALHD_API_NAME, &chd_dec_fops); if (adp->chd_dec_major < 0) { BCMLOG_ERR("Failed to create config dev\n"); rc = adp->chd_dec_major; goto fail; } /* register crystalhd class */ crystalhd_class = class_create(THIS_MODULE, "crystalhd"); if (IS_ERR(crystalhd_class)) { BCMLOG_ERR("failed to create class\n"); goto fail; } dev = device_create(crystalhd_class, NULL, MKDEV(adp->chd_dec_major, 0), NULL, "crystalhd"); if (!dev) { BCMLOG_ERR("failed to create device\n"); goto device_create_fail; } rc = crystalhd_create_elem_pool(adp, BC_LINK_ELEM_POOL_SZ); if (rc) { BCMLOG_ERR("failed to create device\n"); goto elem_pool_fail; } /* Allocate general purpose ioctl pool. */ for (i = 0; i < CHD_IODATA_POOL_SZ; i++) { /* FIXME: jarod: why atomic? */ temp = kzalloc(sizeof(crystalhd_ioctl_data), GFP_ATOMIC); if (!temp) { BCMLOG_ERR("ioctl data pool kzalloc failed\n"); rc = -ENOMEM; goto kzalloc_fail; } /* Add to global pool.. */ chd_dec_free_iodata(adp, temp, 0); } return 0; kzalloc_fail: crystalhd_delete_elem_pool(adp); elem_pool_fail: device_destroy(crystalhd_class, MKDEV(adp->chd_dec_major, 0)); device_create_fail: class_destroy(crystalhd_class); fail: return rc; }
static int pi433_probe(struct spi_device *spi) { struct pi433_device *device; int retval; /* setup spi parameters */ spi->mode = 0x00; spi->bits_per_word = 8; /* * spi->max_speed_hz = 10000000; * 1MHz already set by device tree overlay */ retval = spi_setup(spi); if (retval) { dev_dbg(&spi->dev, "configuration of SPI interface failed!\n"); return retval; } dev_dbg(&spi->dev, "spi interface setup: mode 0x%2x, %d bits per word, %dhz max speed", spi->mode, spi->bits_per_word, spi->max_speed_hz); /* Ping the chip by reading the version register */ retval = spi_w8r8(spi, 0x10); if (retval < 0) return retval; switch (retval) { case 0x24: dev_dbg(&spi->dev, "found pi433 (ver. 0x%x)", retval); break; default: dev_dbg(&spi->dev, "unknown chip version: 0x%x", retval); return -ENODEV; } /* Allocate driver data */ device = kzalloc(sizeof(*device), GFP_KERNEL); if (!device) return -ENOMEM; /* Initialize the driver data */ device->spi = spi; device->rx_active = false; device->tx_active = false; device->interrupt_rx_allowed = false; /* init rx buffer */ device->rx_buffer = kmalloc(MAX_MSG_SIZE, GFP_KERNEL); if (!device->rx_buffer) { retval = -ENOMEM; goto RX_failed; } /* init wait queues */ init_waitqueue_head(&device->tx_wait_queue); init_waitqueue_head(&device->rx_wait_queue); init_waitqueue_head(&device->fifo_wait_queue); /* init fifo */ INIT_KFIFO(device->tx_fifo); /* init mutexes and locks */ mutex_init(&device->tx_fifo_lock); mutex_init(&device->rx_lock); /* setup GPIO (including irq_handler) for the different DIOs */ retval = setup_gpio(device); if (retval) { dev_dbg(&spi->dev, "setup of GPIOs failed"); goto GPIO_failed; } /* setup the radio module */ retval = rf69_set_mode(spi, standby); if (retval < 0) goto minor_failed; retval = rf69_set_data_mode(spi, DATAMODUL_MODE_PACKET); if (retval < 0) goto minor_failed; retval = rf69_enable_amplifier(spi, MASK_PALEVEL_PA0); if (retval < 0) goto minor_failed; retval = rf69_disable_amplifier(spi, MASK_PALEVEL_PA1); if (retval < 0) goto minor_failed; retval = rf69_disable_amplifier(spi, MASK_PALEVEL_PA2); if (retval < 0) goto minor_failed; retval = rf69_set_output_power_level(spi, 13); if (retval < 0) goto minor_failed; retval = rf69_set_antenna_impedance(spi, fifty_ohm); if (retval < 0) goto minor_failed; /* determ minor number */ retval = pi433_get_minor(device); if (retval) { dev_dbg(&spi->dev, "get of minor number failed"); goto minor_failed; } /* create device */ device->devt = MKDEV(MAJOR(pi433_dev), device->minor); device->dev = device_create(pi433_class, &spi->dev, device->devt, device, "pi433.%d", device->minor); if (IS_ERR(device->dev)) { pr_err("pi433: device register failed\n"); retval = PTR_ERR(device->dev); goto device_create_failed; } else { dev_dbg(device->dev, "created device for major %d, minor %d\n", MAJOR(pi433_dev), device->minor); } /* start tx thread */ device->tx_task_struct = kthread_run(pi433_tx_thread, device, "pi433.%d_tx_task", device->minor); if (IS_ERR(device->tx_task_struct)) { dev_dbg(device->dev, "start of send thread failed"); retval = PTR_ERR(device->tx_task_struct); goto send_thread_failed; } /* create cdev */ device->cdev = cdev_alloc(); if (!device->cdev) { dev_dbg(device->dev, "allocation of cdev failed"); goto cdev_failed; } device->cdev->owner = THIS_MODULE; cdev_init(device->cdev, &pi433_fops); retval = cdev_add(device->cdev, device->devt, 1); if (retval) { dev_dbg(device->dev, "register of cdev failed"); goto del_cdev; } /* spi setup */ spi_set_drvdata(spi, device); return 0; del_cdev: cdev_del(device->cdev); cdev_failed: kthread_stop(device->tx_task_struct); send_thread_failed: device_destroy(pi433_class, device->devt); device_create_failed: pi433_free_minor(device); minor_failed: free_gpio(device); GPIO_failed: kfree(device->rx_buffer); RX_failed: kfree(device); return retval; }
/*[Tag000] * 当模块加载时,调用;但是为什么要放在最后来实现他呢,看到Tag002时,你应该就明白了; */ int scull_init_module(void) { int result, i; dev_t dev = 0; /* [Tag001] */ /* [1]分配设备编号 */ /* * Get a range of minor numbers to work with, asking for a dynamic * major unless directed otherwise at load time. */ if (scull_major) { /* 预先自己指定了主设备号 */ dev = MKDEV(scull_major, scull_minor); /* 利用主设备号,找到设备编号给方法1用 */ result = register_chrdev_region(dev, scull_nr_devs, "scull"); } else { /* 动态自己生成设备编号,然后再利用设备编号得到主设备号; 记住如果用这个方法那么就要后建设备文件了,因为不能提前知道主号 当然也可以利用ldd3书中提供的脚本,巨方便&&通用 */ result = alloc_chrdev_region(&dev, scull_minor, scull_nr_devs, "scull"); scull_major = MAJOR(dev); } if (result < 0) { printk(KERN_WARNING "scull: can't get major %d\n", scull_major); return result; } /*[2]设备对象实例化*/ /* * allocate the devices -- we can't have them static, as the number * can be specified at load time */ scull_devices = kmalloc(scull_nr_devs * sizeof(struct scull_dev), GFP_KERNEL); if (!scull_devices) { result = -ENOMEM; goto fail; /* Make this more graceful */ } memset(scull_devices, 0, scull_nr_devs * sizeof(struct scull_dev)); /* [3]在这里初始化设备用了2.6的新方法,在scull_setup_cdev里完成 */ /* Initialize each device. */ for (i = 0; i < scull_nr_devs; i++) { scull_devices[i].quantum = scull_quantum; /* 可以根据自己insmod时传参 来自己改变量子和量子集(指针数组)的大小 */ scull_devices[i].qset = scull_qset; init_MUTEX(&scull_devices[i].sem); scull_setup_cdev(&scull_devices[i], i); /* 在分别完主设备编号后goto Tag002 设备注册 */ } /* At this point call the init function for any friend device */ dev = MKDEV(scull_major, scull_minor + scull_nr_devs); dev += scull_p_init(dev); dev += scull_access_init(dev); #ifdef SCULL_DEBUG /* only when debugging */ scull_create_proc(); #endif return 0; /* succeed */ fail: scull_cleanup_module(); return result; }