⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dell_rbu.c

📁 对于那些带有区码限制的DVD光驱
💻 C
📖 第 1 页 / 共 2 页
字号:
	 * Re-initialize the rbu_data variables after a free	 */	rbu_data.image_update_ordernum = -1;	rbu_data.image_update_buffer = NULL;	rbu_data.image_update_buffer_size = 0;	rbu_data.bios_image_size = 0;	rbu_data.dma_alloc = 0;}/* * img_update_realloc: This function allocates the contiguous pages to * accommodate the requested size of data. The memory address and size * values are stored globally and on every call to this function the new * size is checked to see if more data is required than the existing size. * If true the previous memory is freed and new allocation is done to * accommodate the new size. If the incoming size is less then than the * already allocated size, then that memory is reused. This function is * called with lock held and returns with lock held. */static int img_update_realloc(unsigned long size){	unsigned char *image_update_buffer = NULL;	unsigned long rc;	unsigned long img_buf_phys_addr;	int ordernum;	int dma_alloc = 0;	/*	 * check if the buffer of sufficient size has been	 * already allocated	 */	if (rbu_data.image_update_buffer_size >= size) {		/*		 * check for corruption		 */		if ((size != 0) && (rbu_data.image_update_buffer == NULL)) {			printk(KERN_ERR "dell_rbu:%s: corruption "				"check failed\n", __FUNCTION__);			return -EINVAL;		}		/*		 * we have a valid pre-allocated buffer with		 * sufficient size		 */		return 0;	}	/*	 * free any previously allocated buffer	 */	img_update_free();	spin_unlock(&rbu_data.lock);	ordernum = get_order(size);	image_update_buffer =		(unsigned char *) __get_free_pages(GFP_KERNEL, ordernum);	img_buf_phys_addr =		(unsigned long) virt_to_phys(image_update_buffer);	if (img_buf_phys_addr > BIOS_SCAN_LIMIT) {		free_pages((unsigned long) image_update_buffer, ordernum);		ordernum = -1;		image_update_buffer = dma_alloc_coherent(NULL, size,			&dell_rbu_dmaaddr, GFP_KERNEL);		dma_alloc = 1;	}	spin_lock(&rbu_data.lock);	if (image_update_buffer != NULL) {		rbu_data.image_update_buffer = image_update_buffer;		rbu_data.image_update_buffer_size = size;		rbu_data.bios_image_size =			rbu_data.image_update_buffer_size;		rbu_data.image_update_ordernum = ordernum;		rbu_data.dma_alloc = dma_alloc;		rc = 0;	} else {		pr_debug("Not enough memory for image update:"			"size = %ld\n", size);		rc = -ENOMEM;	}	return rc;}static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count){	int retval;	size_t bytes_left;	size_t data_length;	char *ptempBuf = buffer;	/* check to see if we have something to return */	if (rbu_data.num_packets == 0) {		pr_debug("read_packet_data: no packets written\n");		retval = -ENOMEM;		goto read_rbu_data_exit;	}	if (pos > rbu_data.imagesize) {		retval = 0;		printk(KERN_WARNING "dell_rbu:read_packet_data: "			"data underrun\n");		goto read_rbu_data_exit;	}	bytes_left = rbu_data.imagesize - pos;	data_length = min(bytes_left, count);	if ((retval = packet_read_list(ptempBuf, &data_length)) < 0)		goto read_rbu_data_exit;	if ((pos + count) > rbu_data.imagesize) {		rbu_data.packet_read_count = 0;		/* this was the last copy */		retval = bytes_left;	} else		retval = count;      read_rbu_data_exit:	return retval;}static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count){	unsigned char *ptemp = NULL;	size_t bytes_left = 0;	size_t data_length = 0;	ssize_t ret_count = 0;	/* check to see if we have something to return */	if ((rbu_data.image_update_buffer == NULL) ||		(rbu_data.bios_image_size == 0)) {		pr_debug("read_rbu_data_mono: image_update_buffer %p ,"			"bios_image_size %lu\n",			rbu_data.image_update_buffer,			rbu_data.bios_image_size);		ret_count = -ENOMEM;		goto read_rbu_data_exit;	}	if (pos > rbu_data.bios_image_size) {		ret_count = 0;		goto read_rbu_data_exit;	}	bytes_left = rbu_data.bios_image_size - pos;	data_length = min(bytes_left, count);	ptemp = rbu_data.image_update_buffer;	memcpy(buffer, (ptemp + pos), data_length);	if ((pos + count) > rbu_data.bios_image_size)		/* this was the last copy */		ret_count = bytes_left;	else		ret_count = count;      read_rbu_data_exit:	return ret_count;}static ssize_t read_rbu_data(struct kobject *kobj, char *buffer,	loff_t pos, size_t count){	ssize_t ret_count = 0;	spin_lock(&rbu_data.lock);	if (!strcmp(image_type, "mono"))		ret_count = read_rbu_mono_data(buffer, pos, count);	else if (!strcmp(image_type, "packet"))		ret_count = read_packet_data(buffer, pos, count);	else		pr_debug("read_rbu_data: invalid image type specified\n");	spin_unlock(&rbu_data.lock);	return ret_count;}static void callbackfn_rbu(const struct firmware *fw, void *context){	int rc = 0;	if (!fw || !fw->size) {		rbu_data.entry_created = 0;		return;	}	spin_lock(&rbu_data.lock);	if (!strcmp(image_type, "mono")) {		if (!img_update_realloc(fw->size))			memcpy(rbu_data.image_update_buffer,				fw->data, fw->size);	} else if (!strcmp(image_type, "packet")) {		/*		 * we need to free previous packets if a		 * new hunk of packets needs to be downloaded		 */		packet_empty_list();		if (packetize_data(fw->data, fw->size))			/* Incase something goes wrong when we are			 * in middle of packetizing the data, we			 * need to free up whatever packets might			 * have been created before we quit.			 */			packet_empty_list();	} else		pr_debug("invalid image type specified.\n");	spin_unlock(&rbu_data.lock);	rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,		"dell_rbu", &rbu_device->dev, &context, callbackfn_rbu);	if (rc)		printk(KERN_ERR			"dell_rbu:%s request_firmware_nowait failed"			" %d\n", __FUNCTION__, rc);	else		rbu_data.entry_created = 1;}static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer,	loff_t pos, size_t count){	int size = 0;	if (!pos)		size = sprintf(buffer, "%s\n", image_type);	return size;}static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer,	loff_t pos, size_t count){	int rc = count;	int req_firm_rc = 0;	int i;	spin_lock(&rbu_data.lock);	/*	 * Find the first newline or space	 */	for (i = 0; i < count; ++i)		if (buffer[i] == '\n' || buffer[i] == ' ') {			buffer[i] = '\0';			break;		}	if (i == count)		buffer[count] = '\0';	if (strstr(buffer, "mono"))		strcpy(image_type, "mono");	else if (strstr(buffer, "packet"))		strcpy(image_type, "packet");	else if (strstr(buffer, "init")) {		/*		 * If due to the user error the driver gets in a bad		 * state where even though it is loaded , the		 * /sys/class/firmware/dell_rbu entries are missing.		 * to cover this situation the user can recreate entries		 * by writing init to image_type.		 */		if (!rbu_data.entry_created) {			spin_unlock(&rbu_data.lock);			req_firm_rc = request_firmware_nowait(THIS_MODULE,				FW_ACTION_NOHOTPLUG, "dell_rbu",				&rbu_device->dev, &context,				callbackfn_rbu);			if (req_firm_rc) {				printk(KERN_ERR					"dell_rbu:%s request_firmware_nowait"					" failed %d\n", __FUNCTION__, rc);				rc = -EIO;			} else				rbu_data.entry_created = 1;			spin_lock(&rbu_data.lock);		}	} else {		printk(KERN_WARNING "dell_rbu: image_type is invalid\n");		spin_unlock(&rbu_data.lock);		return -EINVAL;	}	/* we must free all previous allocations */	packet_empty_list();	img_update_free();	spin_unlock(&rbu_data.lock);	return rc;}static ssize_t read_rbu_packet_size(struct kobject *kobj, char *buffer,	loff_t pos, size_t count){	int size = 0;	if (!pos) {		spin_lock(&rbu_data.lock);		size = sprintf(buffer, "%lu\n", rbu_data.packetsize);		spin_unlock(&rbu_data.lock);	}	return size;}static ssize_t write_rbu_packet_size(struct kobject *kobj, char *buffer,	loff_t pos, size_t count){	unsigned long temp;	spin_lock(&rbu_data.lock);	packet_empty_list();	sscanf(buffer, "%lu", &temp);	if (temp < 0xffffffff)		rbu_data.packetsize = temp;	spin_unlock(&rbu_data.lock);	return count;}static struct bin_attribute rbu_data_attr = {	.attr = {.name = "data",.owner = THIS_MODULE,.mode = 0444},	.read = read_rbu_data,};static struct bin_attribute rbu_image_type_attr = {	.attr = {.name = "image_type",.owner = THIS_MODULE,.mode = 0644},	.read = read_rbu_image_type,	.write = write_rbu_image_type,};static struct bin_attribute rbu_packet_size_attr = {	.attr = {.name = "packet_size",.owner = THIS_MODULE,.mode = 0644},	.read = read_rbu_packet_size,	.write = write_rbu_packet_size,};static int __init dcdrbu_init(void){	int rc = 0;	spin_lock_init(&rbu_data.lock);	init_packet_head();	rbu_device =		platform_device_register_simple("dell_rbu", -1, NULL, 0);	if (!rbu_device) {		printk(KERN_ERR			"dell_rbu:%s:platform_device_register_simple "			"failed\n", __FUNCTION__);		return -EIO;	}	sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_data_attr);	sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr);	sysfs_create_bin_file(&rbu_device->dev.kobj,		&rbu_packet_size_attr);	rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,		"dell_rbu", &rbu_device->dev, &context, callbackfn_rbu);	if (rc)		printk(KERN_ERR "dell_rbu:%s:request_firmware_nowait"			" failed %d\n", __FUNCTION__, rc);	else		rbu_data.entry_created = 1;	return rc;}static __exit void dcdrbu_exit(void){	spin_lock(&rbu_data.lock);	packet_empty_list();	img_update_free();	spin_unlock(&rbu_data.lock);	platform_device_unregister(rbu_device);}module_exit(dcdrbu_exit);module_init(dcdrbu_init);/* vim:noet:ts=8:sw=8*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -