📄 xpram.c
字号:
switch(current_req->cmd) { case READ: do { if ( (fault=xpram_page_in((unsigned long)buffer,page_no)) ) { PRINT_WARN("xpram(dev %d): page in failed for page %ld.\n",dev_no,page_no); break; } sects_to_copy -= XPRAM_SEC_IN_PG; buffer += XPRAM_PGSIZE; page_no++; } while ( sects_to_copy > 0 ); break; case WRITE: do { if ( (fault=xpram_page_out((unsigned long)buffer,page_no)) ) { PRINT_WARN("xpram(dev %d): page out failed for page %ld.\n",dev_no,page_no); break; } sects_to_copy -= XPRAM_SEC_IN_PG; buffer += XPRAM_PGSIZE; page_no++; } while ( sects_to_copy > 0 ); break; default: /* can't happen */ end_request(0); continue; } if ( fault ) end_request(0); else end_request(1); /* success */ }}/* * Kernel interfaces *//* * Parses the kernel parameters given in the kernel parameter line. * The expected format is * <number_of_partitions>[","<partition_size>]* * where * devices is a positive integer that initializes xpram_devs * each size is a non-negative integer possibly followed by a * magnitude (k,K,m,M,g,G), the list of sizes initialises * xpram_sizes * * Arguments * str: substring of kernel parameter line that contains xprams * kernel parameters. * ints: not used -- not in Version > 2.3 any more * * Result 0 on success, -EINVAl else -- only for Version > 2.3 * * Side effects * the global variabls devs is set to the value of * <number_of_partitions> and sizes[i] is set to the i-th * partition size (if provided). A parsing error of a value * results in this value being set to -EINVAL. */#if (XPRAM_VERSION == 22)void xpram_setup (char *str, int *ints)#else int xpram_setup (char *str)#endif /* V22 */{ devs = xpram_read_int(&str); if ( devs != -EINVAL ) if ( xpram_read_size_list_tail(&str,devs,sizes) < 0 ) { PRINT_ERR("error while reading xpram parameters.\n");#if (XPRAM_VERSION == 24) return -EINVAL;#endif /* V24 */ }#if (XPRAM_VERSION == 24) else return 0; else return -EINVAL;#elif (XPRAM_VERSION == 22) return; #endif /* V24/V22 */}/* * initialize xpram device driver * * Result: 0 ok * negative number: negative error code */int xpram_init(void){ int result, i; int mem_usable; /* net size of expanded memory */ int mem_needed=0; /* size of expanded memory needed to fullfill * requirements of non-zero parameters in sizes */ int mem_auto_no=0; /* number of (implicit) zero parameters in sizes */ int mem_auto; /* automatically determined device size */#if (XPRAM_VERSION == 24) int minor_length; /* store the length of a minor (w/o '\0') */ int minor_thresh; /* threshhold for minor lenght */ request_queue_t *q; /* request queue */#endif /* V24 */ /* * Copy the (static) cfg variables to public prefixed ones to allow * snoozing with a debugger. */ xpram_rahead = rahead; xpram_blksize = blksize; xpram_hardsect = hardsect; PRINT_INFO("initializing: %s\n",""); /* check arguments */ xpram_major = major; if ( (devs <= 0) || (devs > XPRAM_MAX_DEVS) ) { PRINT_ERR("invalid number %d of devices\n",devs); PRINT_ERR("Giving up xpram\n"); return -EINVAL; } xpram_devs = devs; for (i=0; i < xpram_devs; i++) { if ( sizes[i] < 0 ) { PRINT_ERR("Invalid partition size %d kB\n",xpram_sizes[i]); PRINT_ERR("Giving up xpram\n"); return -EINVAL; } else { xpram_sizes[i] = NEXT4(sizes[i]); /* page align */ if ( sizes[i] ) mem_needed += xpram_sizes[i]; else mem_auto_no++; } } PRINT_DEBUG(" major %d \n", xpram_major); PRINT_INFO(" number of devices (partitions): %d \n", xpram_devs); for (i=0; i < xpram_devs; i++) { if ( sizes[i] ) PRINT_INFO(" size of partition %d: %d kB\n", i, xpram_sizes[i]); else PRINT_INFO(" size of partition %d to be set automatically\n",i); } PRINT_DEBUG(" memory needed (for sized partitions): %d kB\n", mem_needed); PRINT_DEBUG(" partitions to be sized automatically: %d\n", mem_auto_no);#if 0 /* Hardsect can't be changed :( */ /* I try it any way. Yet I must distinguish * between hardsects (to be changed to 4096) * and soft sectors, hard-coded for buffer * sizes within the requests */ if (hardsect != 512) { PRINT_ERR("Can't change hardsect size\n"); hardsect = xpram_hardsect = 512; }#endif PRINT_INFO(" hardsector size: %dB \n",xpram_hardsect); /* * Register your major, and accept a dynamic number */#if (XPRAM_VERSION == 22) result = register_blkdev(xpram_major, "xpram", &xpram_fops);#elif (XPRAM_VERSION == 24) result = devfs_register_blkdev(xpram_major, "xpram", &xpram_devops);#endif /* V22/V24 */ if (result < 0) { PRINT_ERR("Can't get major %d\n",xpram_major); PRINT_ERR("Giving up xpram\n"); return result; }#if (XPRAM_VERSION == 24) xpram_devfs_handle = devfs_mk_dir (NULL, "slram", NULL); devfs_register_series (xpram_devfs_handle, "%u", XPRAM_MAX_DEVS, DEVFS_FL_DEFAULT, XPRAM_MAJOR, 0, S_IFBLK | S_IRUSR | S_IWUSR, &xpram_devops, NULL);#endif /* V22/V24 */ if (xpram_major == 0) xpram_major = result; /* dynamic */ major = xpram_major; /* Use `major' later on to save typing */ result = -ENOMEM; /* for the possible errors */ /* * measure expanded memory */ xpram_mem_avail = xpram_size(); if (!xpram_mem_avail) { PRINT_ERR("No or not enough expanded memory available\n"); PRINT_ERR("Giving up xpram\n"); result = -ENODEV; goto fail_malloc; } PRINT_INFO(" %d kB expanded memory found.\n",xpram_mem_avail ); /* * Assign the other needed values: request, rahead, size, blksize, * hardsect. All the minor devices feature the same value. * Note that `xpram' defines all of them to allow testing non-default * values. A real device could well avoid setting values in global * arrays if it uses the default values. */#if (XPRAM_VERSION == 22) blk_dev[major].request_fn = xpram_request;#elif (XPRAM_VERSION == 24) q = BLK_DEFAULT_QUEUE (major); blk_init_queue (q, xpram_request); blk_queue_headactive (BLK_DEFAULT_QUEUE (major), 0);#endif /* V22/V24 */ read_ahead[major] = xpram_rahead; /* we want to have XPRAM_UNUSED blocks security buffer between devices */ mem_usable=xpram_mem_avail-(XPRAM_UNUSED*(xpram_devs-1)); if ( mem_needed > mem_usable ) { PRINT_ERR("Not enough expanded memory available\n"); PRINT_ERR("Giving up xpram\n"); goto fail_malloc; } /* * partitioning: * xpram_sizes[i] != 0; partition i has size xpram_sizes[i] kB * else: ; all partitions i with xpram_sizesxpram_size[i] * partition equally the remaining space */ if ( mem_auto_no ) { mem_auto=LAST4((mem_usable-mem_needed)/mem_auto_no); PRINT_INFO(" automatically determined partition size: %d kB\n", mem_auto); for (i=0; i < xpram_devs; i++) if (xpram_sizes[i] == 0) xpram_sizes[i] = mem_auto; } blk_size[major]=xpram_sizes; xpram_offsets = kmalloc(xpram_devs * sizeof(int), GFP_KERNEL); if (!xpram_offsets) { PRINT_ERR("Not enough memory for xpram_offsets\n"); PRINT_ERR("Giving up xpram\n"); goto fail_malloc; } xpram_offsets[0] = 0; for (i=1; i < xpram_devs; i++) xpram_offsets[i] = xpram_offsets[i-1] + xpram_sizes[i-1] + XPRAM_UNUSED;#if 0 for (i=0; i < xpram_devs; i++) PRINT_DEBUG(" device(%d) offset = %d kB, size = %d kB\n",i, xpram_offsets[i], xpram_sizes[i]);#endif xpram_blksizes = kmalloc(xpram_devs * sizeof(int), GFP_KERNEL); if (!xpram_blksizes) { PRINT_ERR("Not enough memory for xpram_blksizes\n"); PRINT_ERR("Giving up xpram\n"); goto fail_malloc_blksizes; } for (i=0; i < xpram_devs; i++) /* all the same blocksize */ xpram_blksizes[i] = xpram_blksize; blksize_size[major]=xpram_blksizes; xpram_hardsects = kmalloc(xpram_devs * sizeof(int), GFP_KERNEL); if (!xpram_hardsects) { PRINT_ERR("Not enough memory for xpram_hardsects\n"); PRINT_ERR("Giving up xpram\n"); goto fail_malloc_hardsects; } for (i=0; i < xpram_devs; i++) /* all the same hardsect */ xpram_hardsects[i] = xpram_hardsect; hardsect_size[major]=xpram_hardsects; /* * allocate the devices -- we can't have them static, as the number * can be specified at load time */ xpram_devices = kmalloc(xpram_devs * sizeof (Xpram_Dev), GFP_KERNEL); if (!xpram_devices) { PRINT_ERR("Not enough memory for xpram_devices\n"); PRINT_ERR("Giving up xpram\n"); goto fail_malloc_devices; } memset(xpram_devices, 0, xpram_devs * sizeof (Xpram_Dev));#if (XPRAM_VERSION == 24) minor_length = 1; minor_thresh = 10;#endif /* V24 */ for (i=0; i < xpram_devs; i++) { /* data and usage remain zeroed */ xpram_devices[i].size = xpram_sizes[i]; /* size in kB not in bytes */ atomic_set(&(xpram_devices[i].usage),0);#if (XPRAM_VERSION == 24) if (i == minor_thresh) { minor_length++; minor_thresh *= 10; } xpram_devices[i].device_name = kmalloc(1 + strlen(XPRAM_DEVICE_NAME_PREFIX) + minor_length,GFP_KERNEL); if ( xpram_devices[i].device_name == NULL ) { PRINT_ERR("Not enough memory for xpram_devices[%d].device_name\n",i); PRINT_ERR("Giving up xpram\n"); goto fail_devfs_register; } sprintf(xpram_devices[i].device_name,XPRAM_DEVICE_NAME_PREFIX "%d",i); PRINT_DEBUG("initializing xpram_open for device %d\n",i); PRINT_DEBUG(" size %dkB, name %s, usage: %d\n", xpram_devices[i].size,xpram_devices[i].device_name, atomic_read(&(xpram_devices[i].usage)));#if 0 /* WHY? */ xpram_devices[i].devfs_entry = devfs_register(NULL /* devfs root dir */, xpram_devices[i].device_name, 0, 0 /* flags */, XPRAM_MAJOR,i, 0755 /* access mode */, 0 /* uid */, 0 /* gid */, &xpram_devops, (void *) &(xpram_devices[i]) ); if ( xpram_devices[i].devfs_entry == NULL ) { PRINT_ERR("devfs system registry failed\n"); PRINT_ERR("Giving up xpram\n"); goto fail_devfs_register; }#endif /* WHY? */#endif /* V24 */ } return 0; /* succeed */ /* clean up memory in case of failures */#if (XPRAM_VERSION == 24) fail_devfs_register: for (i=0; i < xpram_devs; i++) { if ( xpram_devices[i].device_name ) kfree(xpram_devices[i].device_name); } kfree(xpram_devices);#endif /* V24 */ fail_malloc_blksizes: kfree (xpram_offsets); fail_malloc_hardsects: kfree (xpram_blksizes); blksize_size[major] = NULL; fail_malloc_devices: kfree(xpram_hardsects); hardsect_size[major] = NULL; fail_malloc: read_ahead[major] = 0;#if (XPRAM_VERSION == 22) blk_dev[major].request_fn = NULL;#endif /* V22 */ /* ??? unregister_chrdev(major, "xpram"); */ unregister_blkdev(major, "xpram"); return result;}/* * Finally, the module stuff */int init_module(void){ int rc = 0; PRINT_INFO ("trying to load module\n"); rc = xpram_init (); if (rc == 0) { PRINT_INFO ("Module loaded successfully\n"); } else { PRINT_WARN ("Module load returned rc=%d\n", rc); } return rc;}void cleanup_module(void){ int i; /* first of all, flush it all and reset all the data structures */ for (i=0; i<xpram_devs; i++) fsync_dev(MKDEV(xpram_major, i)); /* flush the devices */#if (XPRAM_VERSION == 22) blk_dev[major].request_fn = NULL;#endif /* V22 */ read_ahead[major] = 0; blk_size[major] = NULL; kfree(blksize_size[major]); blksize_size[major] = NULL; kfree(hardsect_size[major]); hardsect_size[major] = NULL; kfree(xpram_offsets); /* finally, the usual cleanup */#if (XPRAM_VERSION == 22) unregister_blkdev(major, "xpram");#elif (XPRAM_VERSION == 24) devfs_unregister(xpram_devfs_handle); if (devfs_unregister_blkdev(MAJOR_NR, "xpram")) printk(KERN_WARNING "xpram: cannot unregister blkdev\n");#endif /* V22/V24 */ kfree(xpram_devices);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -