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

📄 comx-hw-comx.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 3 页
字号:
	loopcount=0;	while(loopcount++ < 10000 && COMX_readw(dev, OFF_A_L2_LINKUP) != 1) {		udelay(100);	}	if ( COMX_readw(dev, OFF_A_L2_LINKUP) != 1 ) {		printk(KERN_ERR "%s: error starting firmware, linkup word is %04x\n",			dev->name, COMX_readw(dev, OFF_A_L2_LINKUP));		retval=-EAGAIN;		goto out;	}	ch->init_status |= FW_LOADED;	retval=0;out:	outb_p(board_segment | HICOMX_DISABLE_ALL, dev->base_addr);	outb_p(HICOMX_DATA_MEM, dev->base_addr + 1);	if(saved) {		((struct comx_channel *)saved->priv)->HW_board_on(saved);	}	memory_used[mempos]=saved;	restore_flags(flags);	return retval;}static struct net_device *comx_twin_check(struct net_device *dev){	struct comx_channel *ch = dev->priv;	struct proc_dir_entry *procfile = ch->procdir->parent->subdir;	struct comx_privdata *hw = ch->HW_privdata;	struct net_device *twin;	struct comx_channel *ch_twin;	struct comx_privdata *hw_twin;	for ( ; procfile ; procfile = procfile->next) {			if(!S_ISDIR(procfile->mode)) {			continue;		}			twin=procfile->data;		ch_twin=twin->priv;		hw_twin=ch_twin->HW_privdata;		if (twin != dev && dev->irq && dev->base_addr && dev->mem_start &&		   dev->irq == twin->irq && dev->base_addr == twin->base_addr &&	  	   dev->mem_start == twin->mem_start &&		   hw->channel == (1 - hw_twin->channel) &&		   ch->hardware == ch_twin->hardware) {		   	return twin;		}	}	return NULL;}static int comxhw_write_proc(struct file *file, const char *buffer, 	u_long count, void *data){	struct proc_dir_entry *entry = (struct proc_dir_entry *)data;	struct net_device *dev = entry->parent->data;	struct comx_channel *ch = dev->priv;	struct comx_privdata *hw = ch->HW_privdata;	char *page;	if(ch->init_status & HW_OPEN) {		return -EAGAIN;		}		if (strcmp(FILENAME_FIRMWARE, entry->name) != 0) {		if (!(page = (char *)__get_free_page(GFP_KERNEL))) {			return -ENOMEM;		}		if(copy_from_user(page, buffer, count = (min_t(int, count, PAGE_SIZE))))		{			count = -EFAULT;			goto out;		}		if (page[count-1] == '\n')			page[count-1] = '\0';		else if (count < PAGE_SIZE)			page[count] = '\0';		else if (page[count]) { 			count = -EINVAL;			goto out;		}		page[count]=0;	/* Null terminate */	} else {		byte *tmp;		if (!hw->firmware) {			if ((hw->firmware = kmalloc(sizeof(struct comx_firmware), 			    GFP_KERNEL)) == NULL) {			    	return -ENOMEM;			}			hw->firmware->len = 0;			hw->firmware->data = NULL;		}				if ((tmp = kmalloc(count + file->f_pos, GFP_KERNEL)) == NULL) {			return -ENOMEM;		}				/* Ha nem 0 a fpos, akkor meglevo file-t irunk. Gyenge trukk. */		if (hw->firmware && hw->firmware->len && file->f_pos 		    && hw->firmware->len < count + file->f_pos) {			memcpy(tmp, hw->firmware->data, hw->firmware->len);		}		if (hw->firmware->data) {			kfree(hw->firmware->data);		}		copy_from_user(tmp + file->f_pos, buffer, count);		hw->firmware->len = entry->size = file->f_pos + count;		hw->firmware->data = tmp;		file->f_pos += count;		return count;	}	if (strcmp(entry->name, FILENAME_CHANNEL) == 0) {		hw->channel = simple_strtoul(page, NULL, 0);		if (hw->channel >= MAX_CHANNELNO) {			printk(KERN_ERR "Invalid channel number\n");			hw->channel = 0;		}		if ((ch->twin = comx_twin_check(dev)) != NULL) {			struct comx_channel *twin_ch = ch->twin->priv;			twin_ch->twin = dev;		}	} else if (strcmp(entry->name, FILENAME_IRQ) == 0) {		dev->irq = simple_strtoul(page, NULL, 0);		if (dev->irq == 2) {			dev->irq = 9;		}		if (dev->irq < 3 || dev->irq > 15) {			printk(KERN_ERR "comxhw: Invalid irq number\n");			dev->irq = 0;		}		if ((ch->twin = comx_twin_check(dev)) != NULL) {			struct comx_channel *twin_ch = ch->twin->priv;			twin_ch->twin = dev;		}	} else if (strcmp(entry->name, FILENAME_IO) == 0) {		dev->base_addr = simple_strtoul(page, NULL, 0);		if ((dev->base_addr & 3) != 0 || dev->base_addr < 0x300 		   || dev->base_addr > 0x3fc) {			printk(KERN_ERR "Invalid io value\n");			dev->base_addr = 0;		}		if ((ch->twin = comx_twin_check(dev)) != NULL) {			struct comx_channel *twin_ch = ch->twin->priv;			twin_ch->twin = dev;		}	} else if (strcmp(entry->name, FILENAME_MEMADDR) == 0) {		dev->mem_start = simple_strtoul(page, NULL, 0);		if (dev->mem_start <= 0xf000 && dev->mem_start >= 0xa000) {			dev->mem_start *= 16;		}		if ((dev->mem_start & 0xfff) != 0 || dev->mem_start < COMX_MEM_MIN		    || dev->mem_start + hw->memory_size > COMX_MEM_MAX) {			printk(KERN_ERR "Invalid memory page\n");			dev->mem_start = 0;		}		dev->mem_end = dev->mem_start + hw->memory_size;		if ((ch->twin = comx_twin_check(dev)) != NULL) {			struct comx_channel *twin_ch = ch->twin->priv;			twin_ch->twin = dev;		}	} else if (strcmp(entry->name, FILENAME_CLOCK) == 0) {		if (strncmp("ext", page, 3) == 0) {			hw->clock = 0;		} else {			int kbps;			kbps = simple_strtoul(page, NULL, 0);			hw->clock = kbps ? COMX_CLOCK_CONST/kbps : 0;		}	}out:	free_page((unsigned long)page);	return count;}static int comxhw_read_proc(char *page, char **start, off_t off, int count,	int *eof, void *data){	struct proc_dir_entry *file = (struct proc_dir_entry *)data;	struct net_device *dev = file->parent->data;	struct comx_channel *ch = dev->priv;	struct comx_privdata *hw = ch->HW_privdata;	int len = 0;	if (strcmp(file->name, FILENAME_IO) == 0) {		len = sprintf(page, "0x%03x\n", (unsigned int)dev->base_addr);	} else if (strcmp(file->name, FILENAME_IRQ) == 0) {		len = sprintf(page, "0x%02x\n", dev->irq == 9 ? 2 : dev->irq);	} else if (strcmp(file->name, FILENAME_CHANNEL) == 0) {		len = sprintf(page, "%01d\n", hw->channel);	} else if (strcmp(file->name, FILENAME_MEMADDR) == 0) {		len = sprintf(page, "0x%05x\n", (unsigned int)dev->mem_start);	} else if (strcmp(file->name, FILENAME_TWIN) == 0) {		len = sprintf(page, "%s\n", ch->twin ? ch->twin->name : "none");	} else if (strcmp(file->name, FILENAME_CLOCK) == 0) {		if (hw->clock) {			len = sprintf(page, "%-8d\n", COMX_CLOCK_CONST/hw->clock);		} else {			len = sprintf(page, "external\n");		}	} else if (strcmp(file->name, FILENAME_FIRMWARE) == 0) {		len = min_t(int, FILE_PAGESIZE,			  min_t(int, count, 			      hw->firmware ?			      (hw->firmware->len - off) : 0));		if (len < 0) {			len = 0;		}		*start = hw->firmware ? (hw->firmware->data + off) : NULL;		if (off + len >= (hw->firmware ? hw->firmware->len : 0) || len == 0) {			*eof = 1;		}		return len;	}		if (off >= len) {		*eof = 1;		return 0;	}	*start = page + off;	if (count >= len - off) {		*eof = 1;	}	return min_t(int, count, len - off);}/* Called on echo comx >boardtype */static int COMX_init(struct net_device *dev){	struct comx_channel *ch = dev->priv;	struct comx_privdata *hw;	struct proc_dir_entry *new_file;	if ((ch->HW_privdata = kmalloc(sizeof(struct comx_privdata), 	    GFP_KERNEL)) == NULL) {	    	return -ENOMEM;	}	memset(hw = ch->HW_privdata, 0, sizeof(struct comx_privdata));	if (ch->hardware == &comx_hw || ch->hardware == &cmx_hw) {		hw->memory_size = COMX_MEMORY_SIZE;		hw->io_extent = COMX_IO_EXTENT;		dev->base_addr = COMX_DEFAULT_IO;		dev->irq = COMX_DEFAULT_IRQ;		dev->mem_start = COMX_DEFAULT_MEMADDR;		dev->mem_end = COMX_DEFAULT_MEMADDR + COMX_MEMORY_SIZE;	} else if (ch->hardware == &hicomx_hw) {		hw->memory_size = HICOMX_MEMORY_SIZE;		hw->io_extent = HICOMX_IO_EXTENT;		dev->base_addr = HICOMX_DEFAULT_IO;		dev->irq = HICOMX_DEFAULT_IRQ;		dev->mem_start = HICOMX_DEFAULT_MEMADDR;		dev->mem_end = HICOMX_DEFAULT_MEMADDR + HICOMX_MEMORY_SIZE;	} else {		printk(KERN_ERR "SERIOUS INTERNAL ERROR in %s, line %d\n", __FILE__, __LINE__);	}	if ((new_file = create_proc_entry(FILENAME_IO, S_IFREG | 0644, ch->procdir))	    == NULL) {	    goto cleanup_HW_privdata;	}	new_file->data = (void *)new_file;	new_file->read_proc = &comxhw_read_proc;	new_file->write_proc = &comxhw_write_proc;	new_file->size = 6;	new_file->nlink = 1;	if ((new_file = create_proc_entry(FILENAME_IRQ, S_IFREG | 0644, ch->procdir))	    == NULL) {	    goto cleanup_filename_io;	}	new_file->data = (void *)new_file;	new_file->read_proc = &comxhw_read_proc;	new_file->write_proc = &comxhw_write_proc;	new_file->size = 5;	new_file->nlink = 1;	if ((new_file = create_proc_entry(FILENAME_CHANNEL, S_IFREG | 0644, 	    ch->procdir)) == NULL) {	    goto cleanup_filename_irq;	}	new_file->data = (void *)new_file;	new_file->read_proc = &comxhw_read_proc;	new_file->write_proc = &comxhw_write_proc;	new_file->size = 2;		// Ezt tudjuk	new_file->nlink = 1;	if (ch->hardware == &hicomx_hw || ch->hardware == &cmx_hw) {		if ((new_file = create_proc_entry(FILENAME_CLOCK, S_IFREG | 0644, 		   ch->procdir)) == NULL) {		    goto cleanup_filename_channel;		}		new_file->data = (void *)new_file;		new_file->read_proc = &comxhw_read_proc;		new_file->write_proc = &comxhw_write_proc;		new_file->size = 9;		new_file->nlink = 1;	}	if ((new_file = create_proc_entry(FILENAME_MEMADDR, S_IFREG | 0644, 	    ch->procdir)) == NULL) {		    goto cleanup_filename_clock;	}	new_file->data = (void *)new_file;	new_file->read_proc = &comxhw_read_proc;	new_file->write_proc = &comxhw_write_proc;	new_file->size = 8;	new_file->nlink = 1;	if ((new_file = create_proc_entry(FILENAME_TWIN, S_IFREG | 0444, 	    ch->procdir)) == NULL) {		    goto cleanup_filename_memaddr;	}	new_file->data = (void *)new_file;	new_file->read_proc = &comxhw_read_proc;	new_file->write_proc = NULL;	new_file->nlink = 1;	if ((new_file = create_proc_entry(FILENAME_FIRMWARE, S_IFREG | 0644, 	    ch->procdir)) == NULL) {		    goto cleanup_filename_twin;	}	new_file->data = (void *)new_file;	new_file->read_proc = &comxhw_read_proc;	new_file->write_proc = &comxhw_write_proc;	new_file->nlink = 1;	if (ch->hardware == &comx_hw) {		ch->HW_board_on = COMX_board_on;		ch->HW_board_off = COMX_board_off;		ch->HW_load_board = COMX_load_board;	} else if (ch->hardware == &cmx_hw) {		ch->HW_board_on = COMX_board_on;		ch->HW_board_off = COMX_board_off;		ch->HW_load_board = CMX_load_board;		ch->HW_set_clock = COMX_set_clock;	} else if (ch->hardware == &hicomx_hw) {		ch->HW_board_on = HICOMX_board_on;		ch->HW_board_off = HICOMX_board_off;		ch->HW_load_board = HICOMX_load_board;		ch->HW_set_clock = COMX_set_clock;	} else {		printk(KERN_ERR "SERIOUS INTERNAL ERROR in %s, line %d\n", __FILE__, __LINE__);	}	ch->HW_access_board = COMX_access_board;	ch->HW_release_board = COMX_release_board;	ch->HW_txe = COMX_txe;	ch->HW_open = COMX_open;	ch->HW_close = COMX_close;	ch->HW_send_packet = COMX_send_packet;	ch->HW_statistics = COMX_statistics;	if ((ch->twin = comx_twin_check(dev)) != NULL) {		struct comx_channel *twin_ch = ch->twin->priv;		twin_ch->twin = dev;	}	MOD_INC_USE_COUNT;	return 0;cleanup_filename_twin:	remove_proc_entry(FILENAME_TWIN, ch->procdir);cleanup_filename_memaddr:	remove_proc_entry(FILENAME_MEMADDR, ch->procdir);cleanup_filename_clock:	if (ch->hardware == &hicomx_hw || ch->hardware == &cmx_hw)		remove_proc_entry(FILENAME_CLOCK, ch->procdir);cleanup_filename_channel:	remove_proc_entry(FILENAME_CHANNEL, ch->procdir);cleanup_filename_irq:	remove_proc_entry(FILENAME_IRQ, ch->procdir);cleanup_filename_io:	remove_proc_entry(FILENAME_IO, ch->procdir);cleanup_HW_privdata:	kfree(ch->HW_privdata);	return -EIO;}/* Called on echo valami >boardtype */static int COMX_exit(struct net_device *dev){	struct comx_channel *ch = dev->priv;	struct comx_privdata *hw = ch->HW_privdata;	if (hw->firmware) {		if (hw->firmware->data) kfree(hw->firmware->data);		kfree(hw->firmware);	} if (ch->twin) {		struct comx_channel *twin_ch = ch->twin->priv;		twin_ch->twin = NULL;	}		kfree(ch->HW_privdata);	remove_proc_entry(FILENAME_IO, ch->procdir);	remove_proc_entry(FILENAME_IRQ, ch->procdir);	remove_proc_entry(FILENAME_CHANNEL, ch->procdir);	remove_proc_entry(FILENAME_MEMADDR, ch->procdir);	remove_proc_entry(FILENAME_FIRMWARE, ch->procdir);	remove_proc_entry(FILENAME_TWIN, ch->procdir);	if (ch->hardware == &hicomx_hw || ch->hardware == &cmx_hw) {		remove_proc_entry(FILENAME_CLOCK, ch->procdir);	}	MOD_DEC_USE_COUNT;	return 0;}static int COMX_dump(struct net_device *dev){	printk(KERN_INFO "%s: COMX_dump called, why ?\n", dev->name);	return 0;}static struct comx_hardware comx_hw = {	"comx",	VERSION,	COMX_init,	COMX_exit,	COMX_dump,	NULL};static struct comx_hardware cmx_hw = {	"cmx",	VERSION,	COMX_init,	COMX_exit,	COMX_dump,	NULL};static struct comx_hardware hicomx_hw = {	"hicomx",	VERSION,	COMX_init,	COMX_exit,	COMX_dump,	NULL};#ifdef MODULE#define comx_hw_comx_init init_module#endifint __init comx_hw_comx_init(void){	comx_register_hardware(&comx_hw);	comx_register_hardware(&cmx_hw);	comx_register_hardware(&hicomx_hw);	memset(memory_used, 0, sizeof(memory_used));	return 0;}#ifdef MODULEvoid cleanup_module(void){	comx_unregister_hardware("comx");	comx_unregister_hardware("cmx");	comx_unregister_hardware("hicomx");}#endif

⌨️ 快捷键说明

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