www.pudn.com > 422.rar > main.c


/* main.c
 * Linux serial-bus device driver.
 * Written by wang song yue--bupt  email:wsy5228@sina.com
 * This software is released under the GPL-License.
 * Version 0.1  28 october 2005
 */

#define EXPORT_SYMTAB

#include 
#if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS)
#define MODVERSIONS
#endif

#include 

#if defined (MODVERSIONS)
#include 
#endif

#include 
#include 
#include 
#include 
#include 
#include 

#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,2,19))
#include 
#else
#include 
#endif

#if !defined (__GENKSYMS__) 
#if (defined (MODVERSIONS) && !defined(NOVER))
#include 
#include "../include/main.ver"
#endif
#endif

#include "../include/main.h"
#include "../include/modparms.h"
#include "../include/setup.h"
#include "../include/proc.h"
#include "../include/open.h"
#include "../include/close.h"
#include "../include/read.h"
#include "../include/irq.h"
#include "../include/ioctl.h"
#include "../include/write.h"

#define EXPORT_SYMTAB
/* Module parameters, some must be supplied at module loading time */
int major=TTS_MAJOR;
MODULE_PARM(major,"1i");
int minor[MAX_TOT_CHIPS]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
MODULE_PARM(minor, "1-" __MODULE_STRING(MAX_TOT_CHIPS)"i");
int extended=0;
MODULE_PARM(extended,"1i");
//int pelican=0;
//MODULE_PARM(pelican,"1i");
int baudrate=0;
MODULE_PARM(baudrate,"1i");
char *hw[MAX_HW_CARDS]={"aim104","aim104","aim104","aim104",NULL};
MODULE_PARM(hw, "1-" __MODULE_STRING(MAX_HW_CARDS)"s");
int irq[MAX_IRQ]={59,59,59,59,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_IRQ)"i");
unsigned long io[MAX_HW_CARDS]={0xffd00000,0xffd00008,0xffd00010,0xffd00018,-1,-1,-1,-1};
MODULE_PARM(io, "1-" __MODULE_STRING(MAX_HW_CARDS)"i");
int stdmask=0;
MODULE_PARM(stdmask, "1i");
int extmask=0;
MODULE_PARM(extmask, "1i");
int mo15mask=0;
MODULE_PARM(mo15mask, "1i");

/* Global structures, used to describe the installed hardware. */
struct canhardware_t canhardware;
struct canhardware_t *hardware_p=&canhardware;
struct candevice_t *candevices_p[MAX_HW_CARDS];
struct chip_t *chips_p[MAX_TOT_CHIPS];
struct msgobj_t *objects_p[MAX_TOT_MSGOBJS];

/* Pointers to dynamically allocated memory are maintained in a linked list
 * to ease memory deallocation.
 */
struct mem_addr *mem_head=NULL;

#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,2,19))
struct file_operations can_fops=
{
	NULL,				/* llseek */
	read:		serial_read,
	write:		serial_write,
	NULL,				/* readdir */
	NULL, 				/* poll */
	ioctl:		serial_ioctl,
	NULL,				/* mmap */
	open:		serial_open,
	NULL,				/* flush */
	release:	serial_close,
	NULL,				/* fsync */
}; 
#else 
struct file_operations can_fops=
{
	owner:		THIS_MODULE,	
	read:		serial_read,
	write:		serial_write,
	ioctl:		serial_ioctl,
	open:		serial_open,
	release:	serial_close,
};
#endif

EXPORT_SYMBOL(can_fops);

int init_module(void)
{
	int res=0,i=0;
	if (parse_mod_parms())
		return -EINVAL;
	if (init_hw_struct())
		return -ENODEV;
	#ifdef CAN_DEBUG
		list_hw();
	#endif
	while(hw[i]!=NULL)
	{
	res=register_chrdev(major,DEVICE_NAME, &can_fops);
	if (res<0) {
		CANMSG("Error registering driver.\n");
		return -ENODEV;
	}
	i++;
        }
	for (i=0; inr_boards; i++) {
	//	printk("i===%d\n",i);
	//	printk("io_addr===========0x%lx\n",candevices_p[i]->io_addr);
		if (candevices_p[i]->hwspecops->request_io(candevices_p[i]->io_addr)) 
		goto memory_error;
	}

	for (i=0; inr_boards; i++) {
		if (candevices_p[i]->hwspecops->reset(i)) 
			goto reset_error;
	}
//printk("main reset(i) 1111111111\n");
	i=0;
	while ( (chips_p[i] != NULL) && (i < MAX_TOT_CHIPS) ) {
	
		if (!strcmp(chips_p[i]->chip_type,"16c554")) {
			if (request_irq(chips_p[i]->chip_irq,
	chips_p[i]->chipspecops->irq_handler,SA_SHIRQ,DEVICE_NAME,chips_p[i]))
				goto interrupt_error;
			else
				DEBUGMSG("Registered interrupt %d\n",chips_p[i]->chip_irq);
		}
		i++;
	}

	for (i=0; inr_boards; i++) {
		if (candevices_p[i]->flags & PROGRAMMABLE_IRQ)
			if (candevices_p[i]->hwspecops->program_irq(i))
				goto interrupt_error;
	}

	spin_lock_init(&hardware_p->rtr_lock);
	hardware_p->rtr_queue=NULL;

#ifdef CONFIG_PROC_FS
	if (can_init_procdir())
		goto proc_error;
#endif

	return 0;

#ifdef CONFIG_PROC_FS
	proc_error: ;
		CANMSG("Error registering /proc entry.\n");
		goto memory_error; 
#endif

	interrupt_error: ;
		CANMSG("Error registering interrupt line.\n");
		goto memory_error;

	reset_error: ;
		goto memory_error;

	memory_error: ;
		for (i=0; inr_boards; i++)
			candevices_p[i]->hwspecops->release_io(candevices_p[i]->io_addr);
		goto register_error;

	register_error: ;
		res=unregister_chrdev(major,DEVICE_NAME);
		if (res<0)
			CANMSG("Error unloading CAN driver, error: %d\n",res);
		else
			CANMSG("Successfully unloaded CAN driver.\n");
		return -ENODEV;

}

void cleanup_module(void)
{
	int res=0,i=0;

#ifdef CONFIG_PROC_FS
	if (can_delete_procdir())
		CANMSG("Error unregistering /proc/can entry.\n"); 
#endif

	while ( (chips_p[i] != NULL) & (i < MAX_TOT_CHIPS) ) {
		free_irq(chips_p[i]->chip_irq, chips_p[i]);
		i++;
	}

	for (i=0; inr_boards; i++) 
		candevices_p[i]->hwspecops->release_io(candevices_p[i]->io_addr);

	if ( del_mem_list() ) 
		CANMSG("Error deallocating memory\n");

	res=unregister_chrdev(major,DEVICE_NAME);
	if (res<0)
		CANMSG("Error unregistering TTS driver, error: %d\n",res);
}