static int smsdvb_hotplug(struct smscore_device_t *coredev, struct device *device, int arrival) { struct smsclient_params_t params; struct smsdvb_client_t *client; int rc; /* device removal handled by onremove callback */ if (!arrival) return 0; client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL); if (!client) return -ENOMEM; /* register dvb adapter */ rc = dvb_register_adapter(&client->adapter, sms_get_board( smscore_get_board_id(coredev))->name, THIS_MODULE, device, adapter_nr); if (rc < 0) { pr_err("dvb_register_adapter() failed %d\n", rc); goto adapter_error; } dvb_register_media_controller(&client->adapter, coredev->media_dev); /* init dvb demux */ client->demux.dmx.capabilities = DMX_TS_FILTERING; client->demux.filternum = 32; /* todo: nova ??? */ client->demux.feednum = 32; client->demux.start_feed = smsdvb_start_feed; client->demux.stop_feed = smsdvb_stop_feed; rc = dvb_dmx_init(&client->demux); if (rc < 0) { pr_err("dvb_dmx_init failed %d\n", rc); goto dvbdmx_error; } /* init dmxdev */ client->dmxdev.filternum = 32; client->dmxdev.demux = &client->demux.dmx; client->dmxdev.capabilities = 0; rc = dvb_dmxdev_init(&client->dmxdev, &client->adapter); if (rc < 0) { pr_err("dvb_dmxdev_init failed %d\n", rc); goto dmxdev_error; } /* init and register frontend */ memcpy(&client->frontend.ops, &smsdvb_fe_ops, sizeof(struct dvb_frontend_ops)); switch (smscore_get_device_mode(coredev)) { case DEVICE_MODE_DVBT: case DEVICE_MODE_DVBT_BDA: client->frontend.ops.delsys[0] = SYS_DVBT; break; case DEVICE_MODE_ISDBT: case DEVICE_MODE_ISDBT_BDA: client->frontend.ops.delsys[0] = SYS_ISDBT; break; } rc = dvb_register_frontend(&client->adapter, &client->frontend); if (rc < 0) { pr_err("frontend registration failed %d\n", rc); goto frontend_error; } params.initial_id = 1; params.data_type = MSG_SMS_DVBT_BDA_DATA; params.onresponse_handler = smsdvb_onresponse; params.onremove_handler = smsdvb_onremove; params.context = client; rc = smscore_register_client(coredev, ¶ms, &client->smsclient); if (rc < 0) { pr_err("smscore_register_client() failed %d\n", rc); goto client_error; } client->coredev = coredev; init_completion(&client->tune_done); init_completion(&client->stats_done); kmutex_lock(&g_smsdvb_clientslock); list_add(&client->entry, &g_smsdvb_clients); kmutex_unlock(&g_smsdvb_clientslock); client->event_fe_state = -1; client->event_unc_state = -1; sms_board_dvb3_event(client, DVB3_EVENT_HOTPLUG); sms_board_setup(coredev); if (smsdvb_debugfs_create(client) < 0) pr_info("failed to create debugfs node\n"); dvb_create_media_graph(&client->adapter); pr_info("DVB interface registered.\n"); return 0; client_error: dvb_unregister_frontend(&client->frontend); frontend_error: dvb_dmxdev_release(&client->dmxdev); dmxdev_error: dvb_dmx_release(&client->demux); dvbdmx_error: smsdvb_media_device_unregister(client); dvb_unregister_adapter(&client->adapter); adapter_error: kfree(client); return rc; }
/* * s5fs_rmdir: * s5fs_rmdir removes the directory called name from dir. the directory * to be removed must be empty (except for . and .. of course). * param *parent: the pointer to the parent dir of the name specified * param *name: name string * param namelen: the length of the name string * return: 0 on success; negative numbers on a variety of errors */ static int s5fs_rmdir(vnode_t *parent, const char *name, size_t namelen) { dbg(DBG_S5FS, "{\n"); KASSERT(parent != NULL); KASSERT(name != NULL); KASSERT(namelen <= NAME_LEN - 1); KASSERT((uint32_t)parent->vn_len == VNODE_TO_S5INODE(parent)->s5_size); kmutex_lock(&parent->vn_mutex); int inode_number = 0; if ((inode_number = s5_find_dirent(parent, name, namelen)) < 0) { kmutex_unlock(&parent->vn_mutex); /* Need vput? */ return inode_number; } /* May block here */ vnode_t* vn = vget(parent->vn_fs, inode_number); KASSERT(vn != NULL); if (!S_ISDIR(vn->vn_mode)) { /* May block here */ vput(vn); kmutex_unlock(&parent->vn_mutex); return -ENOTDIR; } /* Check empty */ if (VNODE_TO_S5INODE(vn)->s5_size > sizeof(dirent_t)*2) { vput(vn); kmutex_unlock(&parent->vn_mutex); return -ENOTEMPTY; } int ret; if ((ret = s5_remove_dirent(parent, name, namelen)) < 0) { /* May block here */ vput(vn); kmutex_unlock(&parent->vn_mutex); return ret; } /* Decrease the linkcount because .. is removed */ s5_inode_t* parent_inode = VNODE_TO_S5INODE(parent); parent_inode->s5_linkcount--; s5_dirty_inode(VNODE_TO_S5FS(parent), parent_inode); /* May block here */ vput(vn); kmutex_unlock(&parent->vn_mutex); dbg(DBG_S5FS, "}\n"); return ret; }
/* * Unlocks the mutex for the whole file system */ static void unlock_s5(s5fs_t *fs) { kmutex_unlock(&fs->s5f_mutex); }
/* * s5fs_mknod: * s5fs_mknod creates a special file for the device specified by * 'devid' and an entry for it in 'dir' of the specified name. * param dir: the pointer to the * param name: the name string * param namelen: the length of the name string * param mode: device mode * param devid: device id * return: 0 on success; negative number on a variety of errors */ static int s5fs_mknod(vnode_t *dir, const char *name, size_t namelen, int mode, devid_t devid) { dbg(DBG_S5FS, "{\n"); KASSERT(S_ISCHR(mode) || S_ISBLK(mode)); KASSERT(namelen <= S5_NAME_LEN-1); KASSERT(name != NULL); KASSERT(dir != NULL); vnode_t* vn = NULL; /* Must be non-exist */ vnode_t* result = NULL; KASSERT(0 != s5fs_lookup(dir, name, namelen, &result)); /* lock */ kmutex_lock(&dir->vn_mutex); int ino = 0; if (S_ISCHR(mode)) { if ((ino = s5_alloc_inode(dir->vn_fs, S5_TYPE_CHR, devid)) < 0) { /* Unsuccessfull*/ kmutex_unlock(&dir->vn_mutex); return ino; } }else if (S_ISBLK(mode)) { if ((ino = s5_alloc_inode(dir->vn_fs, S5_TYPE_BLK, devid)) < 0) { /* Unsuccessfull*/ kmutex_unlock(&dir->vn_mutex); return ino; } } else { panic("Impossible to get here!"); } /* May block here */ vn = vget(dir->vn_fs, (ino_t)ino); KASSERT(vn != NULL); KASSERT(vn->vn_vno == (ino_t)ino); int ret = 0; if ((ret = s5_link(dir, vn, name, namelen)) < 0) { /* May block here */ vput(vn); kmutex_unlock(&dir->vn_mutex); return ret; } /* new vnode */ KASSERT(vn->vn_refcount == 1); /* May block here */ vput(vn); kmutex_unlock(&dir->vn_mutex); dbg(DBG_S5FS, "}\n"); return 0; }
/* * s5fs_mkdir: * s5fs_mkdir creates a directory called name in dir * param *dir: the pointer to the vnode object of the parent directory * param *name: the name string * param namelen: the length of the name * return: 0 on success; negative number on a variety of errors */ static int s5fs_mkdir(vnode_t *dir, const char *name, size_t namelen) { dbg(DBG_S5FS, "{\n"); KASSERT(dir != NULL); KASSERT(name != NULL); KASSERT(namelen <= NAME_LEN-1); vnode_t* result = NULL; /* Must be non-exist */ KASSERT(s5fs_lookup(dir, name, namelen, &result) < 0); /* Lock */ kmutex_lock(&dir->vn_mutex); s5_inode_t* dir_inode = VNODE_TO_S5INODE(dir); int parent_link = dir_inode->s5_linkcount; int ino = 0; /* Allocate an inode */ if ((ino = s5_alloc_inode(dir->vn_fs, S5_TYPE_DIR, 0)) < 0) { /* Unsuccess */ kmutex_unlock(&dir->vn_mutex); return ino; } /* May block here */ vnode_t* vn = vget(dir->vn_fs, ino); KASSERT(vn != NULL); int ret = 0; ret = s5_link(dir, vn, name, namelen); if (ret < 0) { /* May block here */ vput(vn); kmutex_unlock(&dir->vn_mutex); return -1; } s5_inode_t* inode = VNODE_TO_S5INODE(vn); ret = s5_link(vn, vn, ".", 1); if (ret < 0) { /* May block here */ vput(vn); kmutex_unlock(&dir->vn_mutex); return -1; } int a = inode->s5_direct_blocks[0]; ret = s5_link(vn, dir, "..", 2); if (ret < 0) { /* May block here */ vput(vn); kmutex_unlock(&dir->vn_mutex); return -1; } int b = inode->s5_direct_blocks[0]; if (a != b) { KASSERT(0); b = a; } KASSERT(inode->s5_linkcount == 2); /* one is VFS, one is from the parent */ /* Not clear */ KASSERT(parent_link + 1 == dir_inode->s5_linkcount); /* May block here */ vput(vn); kmutex_unlock(&dir->vn_mutex); KASSERT(ret == 0); dbg(DBG_S5FS, "}\n"); return ret; }
/* * s5fs_read_vnode: * s5fs_read_vnode will be passed a vnode_t*, which will have its vn_fs * and vn_vno fields initialized. * param *vnode: the pointer to the vnode object */ static void s5fs_read_vnode(vnode_t *vnode) { dbg(DBG_S5FS, "{\n"); KASSERT(vnode != NULL); KASSERT(vnode->vn_fs != NULL); kmutex_lock(&vnode->vn_mutex); pframe_t* page = NULL; int ret = pframe_get(S5FS_TO_VMOBJ(FS_TO_S5FS(vnode->vn_fs)), S5_INODE_BLOCK(vnode->vn_vno), &page); KASSERT(ret == 0); KASSERT(page != NULL); pframe_pin(page); s5_inode_t* inode = ((s5_inode_t*)page->pf_addr) + S5_INODE_OFFSET(vnode->vn_vno); inode->s5_linkcount++; s5_dirty_inode(VNODE_TO_S5FS(vnode), inode); vnode->vn_i = inode; vnode->vn_len = inode->s5_size; switch(inode->s5_type) { case S5_TYPE_DIR: { vnode->vn_mode = S_IFDIR; vnode->vn_ops = &s5fs_dir_vops; break; } case S5_TYPE_DATA: { vnode->vn_mode = S_IFREG; vnode->vn_ops = &s5fs_file_vops; break; } case S5_TYPE_CHR: { vnode->vn_mode = S_IFCHR; vnode->vn_ops = NULL; vnode->vn_devid = (devid_t)(inode->s5_indirect_block); vnode->vn_cdev = bytedev_lookup(vnode->vn_devid); break; } case S5_TYPE_BLK: { vnode->vn_mode = S_IFBLK; vnode->vn_ops = NULL; vnode->vn_devid = (devid_t)(inode->s5_indirect_block); vnode->vn_bdev = blockdev_lookup(vnode->vn_devid); break; } default: { panic("inode %d has unknown/invalid type %d!!\n", (int)vnode->vn_vno, (int)inode->s5_type); } } kmutex_unlock(&vnode->vn_mutex); dbg(DBG_S5FS, "}\n"); }
STATIC int fat_getdents64(fs_handle h, struct linux_dirent64 *dirp, u32 buf_size) { fat_file_handle *fh = h; int rc; if (!fh->e->directory && !fh->e->volume_id) return -ENOTDIR; fat_fs_device_data *dd = fh->fs->device_data; fat_walk_dir_ctx walk_ctx = {0}; getdents64_walk_ctx ctx = { .dirp = dirp, .buf_size = buf_size, .fh = fh, .offset = 0, .curr_file_index = 0, .rc = 0, }; u32 cluster_to_use = 0; if (fh->e == dd->root_entry) { cluster_to_use = dd->root_cluster; } else { cluster_to_use = fat_get_first_cluster(fh->e); } rc = fat_walk_directory(&walk_ctx, dd->hdr, dd->type, NULL, cluster_to_use, fat_getdents64_cb, &ctx, /* arg */ 0 /* depth level */); if (rc != 0) return rc; if (ctx.rc != 0) return (int)ctx.rc; return (int) ctx.offset; } STATIC void fat_exclusive_lock(filesystem *fs) { if (!(fs->flags & VFS_FS_RW)) return; /* read-only: no lock is needed */ fat_fs_device_data *d = fs->device_data; kmutex_lock(&d->ex_mutex); } STATIC void fat_exclusive_unlock(filesystem *fs) { if (!(fs->flags & VFS_FS_RW)) return; /* read-only: no lock is needed */ fat_fs_device_data *d = fs->device_data; kmutex_unlock(&d->ex_mutex); } STATIC void fat_shared_lock(filesystem *fs) { if (!(fs->flags & VFS_FS_RW)) return; /* read-only: no lock is needed */ NOT_IMPLEMENTED(); } STATIC void fat_shared_unlock(filesystem *fs) { if (!(fs->flags & VFS_FS_RW)) return; /* read-only: no lock is needed */ NOT_IMPLEMENTED(); } STATIC void fat_file_exlock(fs_handle h) { // TODO: introduce a real per-file lock fat_exclusive_lock(get_fs(h)); }
/* * See the comment in vnode.h for what is expected of this function. * * You need to create the "." and ".." directory entries in the new * directory. These are simply links to the new directory and its * parent. * * When this function returns, the inode refcount on the parent should * be incremented, and the inode refcount on the new directory should be * 1. It might make more sense for the inode refcount on the new * directory to be 2 (since "." refers to it as well as its entry in the * parent dir), but convention is that empty directories have only 1 * link. * * You probably want to use s5_alloc_inode, and s5_link(). * * Assert, a lot. */ static int s5fs_mkdir(vnode_t *dir, const char *name, size_t namelen) { static const char *dotstring = "."; static const char *dotdotstring = ".."; KASSERT(namelen < NAME_LEN); KASSERT(dir->vn_ops->mkdir != NULL); kmutex_lock(&dir->vn_mutex); fs_t *fs = VNODE_TO_S5FS(dir)->s5f_fs; int ino = s5_alloc_inode(fs, S5_TYPE_DIR, NULL); if (ino < 0){ dbg(DBG_S5FS, "unable to alloc a new inode\n"); kmutex_unlock(&dir->vn_mutex); return ino; } vnode_t *child = vget(fs, ino); kmutex_lock(&child->vn_mutex); /* make sure the state of the new vnode is correct */ assert_new_vnode_state(child, ino, S5_TYPE_DIR, 0); int link_res = s5_link(child, child, dotstring, 1); if (link_res < 0){ dbg(DBG_S5FS, "error creating entry for \'.\' in new directory\n"); /* TODO make sure we should be vputting */ /*s5_free_inode(child);*/ vput(child); kmutex_unlock(&child->vn_mutex); kmutex_unlock(&dir->vn_mutex); return link_res; } KASSERT(VNODE_TO_S5INODE(child)->s5_linkcount == 1); link_res = s5_link(child, dir, dotdotstring, 2); if (link_res < 0){ dbg(DBG_S5FS, "error creating entry for \'..\' in new directory\n"); /*s5_free_inode(child);*/ vput(child); kmutex_unlock(&child->vn_mutex); kmutex_unlock(&dir->vn_mutex); return link_res; } link_res = s5_link(dir, child, name, namelen); if (link_res < 0){ dbg(DBG_S5FS, "error creating entry for new directory in parent dir\n"); /*s5_free_inode(child);*/ vput(child); kmutex_unlock(&child->vn_mutex); kmutex_unlock(&dir->vn_mutex); return link_res; } KASSERT(VNODE_TO_S5INODE(child)->s5_linkcount == 2); vput(child); KASSERT(child->vn_refcount - child->vn_nrespages == 0); kmutex_unlock(&child->vn_mutex); kmutex_unlock(&dir->vn_mutex); return 0; }
static int smsdvb_hotplug(struct smscore_device_t *coredev, struct device *device, int arrival) { struct smsclient_params_t params; struct smsdvb_client_t *client; int rc; /* device removal handled by onremove callback */ if (!arrival) return 0; if (smscore_get_device_mode(coredev) != 4) { sms_err("SMS Device mode is not set for " "DVB operation."); return 0; } client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL); if (!client) { sms_err("kmalloc() failed"); return -ENOMEM; } /* register dvb adapter */ rc = dvb_register_adapter(&client->adapter, sms_get_board( smscore_get_board_id(coredev))->name, THIS_MODULE, device, adapter_nr); if (rc < 0) { sms_err("dvb_register_adapter() failed %d", rc); goto adapter_error; } /* init dvb demux */ client->demux.dmx.capabilities = DMX_TS_FILTERING; client->demux.filternum = 32; /* todo: nova ??? */ client->demux.feednum = 32; client->demux.start_feed = smsdvb_start_feed; client->demux.stop_feed = smsdvb_stop_feed; rc = dvb_dmx_init(&client->demux); if (rc < 0) { sms_err("dvb_dmx_init failed %d", rc); goto dvbdmx_error; } /* init dmxdev */ client->dmxdev.filternum = 32; client->dmxdev.demux = &client->demux.dmx; client->dmxdev.capabilities = 0; rc = dvb_dmxdev_init(&client->dmxdev, &client->adapter); if (rc < 0) { sms_err("dvb_dmxdev_init failed %d", rc); goto dmxdev_error; } /* init and register frontend */ memcpy(&client->frontend.ops, &smsdvb_fe_ops, sizeof(struct dvb_frontend_ops)); rc = dvb_register_frontend(&client->adapter, &client->frontend); if (rc < 0) { sms_err("frontend registration failed %d", rc); goto frontend_error; } params.initial_id = 1; params.data_type = MSG_SMS_DVBT_BDA_DATA; params.onresponse_handler = smsdvb_onresponse; params.onremove_handler = smsdvb_onremove; params.context = client; rc = smscore_register_client(coredev, ¶ms, &client->smsclient); if (rc < 0) { sms_err("smscore_register_client() failed %d", rc); goto client_error; } client->coredev = coredev; init_completion(&client->tune_done); init_completion(&client->stat_done); kmutex_lock(&g_smsdvb_clientslock); list_add(&client->entry, &g_smsdvb_clients); kmutex_unlock(&g_smsdvb_clientslock); sms_info("success"); return 0; client_error: dvb_unregister_frontend(&client->frontend); frontend_error: dvb_dmxdev_release(&client->dmxdev); dmxdev_error: dvb_dmx_release(&client->demux); dvbdmx_error: dvb_unregister_adapter(&client->adapter); adapter_error: kfree(client); return rc; }
static int smsdvb_hotplug(struct smscore_device_t *coredev, struct device *device, int arrival) { struct smsclient_params_t params; struct smsdvb_client_t *client; int rc; int mode = smscore_get_device_mode(coredev); //mode = 6; /* device removal handled by onremove callback */ if (!arrival) return 0; if ( (mode != DEVICE_MODE_DVBT_BDA) && (mode != DEVICE_MODE_ISDBT_BDA) ) { sms_err("SMS Device mode is not set for " "DVB operation."); return 0; } client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL); if (!client) { sms_err("kmalloc() failed"); return -ENOMEM; } /* register dvb adapter */ #ifdef SMS_DVB_OLD_DVB_REGISTER_ADAPTER rc = dvb_register_adapter(&client->adapter, sms_get_board(smscore_get_board_id(coredev))-> name, THIS_MODULE, device); #else rc = dvb_register_adapter(&client->adapter, sms_get_board(smscore_get_board_id(coredev))-> name, THIS_MODULE, device, adapter_nr); #endif if (rc < 0) { sms_err("dvb_register_adapter() failed %d", rc); goto adapter_error; } /* init dvb demux */ client->demux.dmx.capabilities = DMX_TS_FILTERING; client->demux.filternum = 32; /* todo: nova ??? */ client->demux.feednum = 32; client->demux.start_feed = smsdvb_start_feed; client->demux.stop_feed = smsdvb_stop_feed; rc = dvb_dmx_init(&client->demux); if (rc < 0) { sms_err("dvb_dmx_init failed %d", rc); goto dvbdmx_error; } /* init dmxdev */ client->dmxdev.filternum = 32; client->dmxdev.demux = &client->demux.dmx; client->dmxdev.capabilities = 0; rc = dvb_dmxdev_init(&client->dmxdev, &client->adapter); if (rc < 0) { sms_err("dvb_dmxdev_init failed %d", rc); goto dmxdev_error; } //add by luis printk("debug: %s, %d, %s>>>>>>>>>>>>>>>>>>>>\n", __FILE__, __LINE__, __FUNCTION__); //add by luis /* init and register frontend */ memcpy(&client->frontend.ops, &smsdvb_fe_ops, sizeof(struct dvb_frontend_ops)); //add by luis printk("debug: %s, %d, %s>>>>>>>>>>>>>>>>>>>>\n", __FILE__, __LINE__, __FUNCTION__); //add by luis rc = dvb_register_frontend(&client->adapter, &client->frontend); if (rc < 0) { sms_err("frontend registration failed %d", rc); goto frontend_error; } params.initial_id = 1; params.data_type = MSG_SMS_DVBT_BDA_DATA; params.onresponse_handler = smsdvb_onresponse; params.onremove_handler = smsdvb_onremove; params.context = client; //add by luis printk("debug: %s, %d, %s>>>>>>>>>>>>>>>>>>>>\n", __FILE__, __LINE__, __FUNCTION__); //add by luis rc = smscore_register_client(coredev, ¶ms, &client->smsclient); if (rc < 0) { sms_err("smscore_register_client() failed %d", rc); goto client_error; } client->coredev = coredev; init_completion(&client->tune_done); init_completion(&client->get_stats_done); kmutex_lock(&g_smsdvb_clientslock); list_add(&client->entry, &g_smsdvb_clients); kmutex_unlock(&g_smsdvb_clientslock); client->event_fe_state = -1; client->event_unc_state = -1; sms_board_dvb3_event(client, DVB3_EVENT_HOTPLUG); //add by luis printk("debug: %s, %d, %s>>>>>>>>>>>>>>>>>>>>\n", __FILE__, __LINE__, __FUNCTION__); //add by luis sms_info("success"); return 0; client_error: dvb_unregister_frontend(&client->frontend); frontend_error: dvb_dmxdev_release(&client->dmxdev); dmxdev_error: dvb_dmx_release(&client->demux); dvbdmx_error: dvb_unregister_adapter(&client->adapter); adapter_error: kfree(client); return rc; }