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


/* setup.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
 */ 

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

#if defined (MODVERSIONS)
#include 
#endif

#include 
#include 

#include "../.support"

#include "../include/main.h"
#include "../include/setup.h"
#include "../include/aim104.h"

extern int s16c554_register(struct chipspecops_t *chipspecops);
extern int aim104_register(struct hwspecops_t *hwspecops);

int init_device_struct(int card);
int init_hwspecops(int card);
int init_chip_struct(int card);
int init_obj_struct(int card, int chip);
int init_chipspecops(int card, int chipnr);

int add_mem_to_list(void *address_p)
{
	struct mem_addr *mem_new;

#ifdef DEBUG_MEM
	DEBUGMSG("add_mem_to_list %p, mem_head=%p\n",address_p, mem_head);
	return 0;
#endif

	mem_new=(struct mem_addr *)kmalloc(sizeof(struct mem_addr),GFP_KERNEL);
	if (mem_new == NULL) {
		CANMSG("Memory list error.\n");
		return -ENOMEM;
	}
	mem_new->next=mem_head;
	mem_new->address=address_p;
	mem_head=mem_new;

	return 0;
}

int del_mem_from_list(void *address_p)
{
	struct mem_addr *mem_search=NULL;
	struct mem_addr *mem_delete=NULL;

#ifdef DEBUG_MEM
	DEBUGMSG("del_mem_from_list %p, mem_head=%p\n", address_p, mem_head);
	return 0;
#endif
	
	mem_search = mem_head;

	if (mem_head->address == address_p) {
		kfree(mem_head->address);
		mem_head=mem_head->next;
		kfree(mem_search);
	}
	else {
		while (mem_search->next->address != address_p)
			mem_search=mem_search->next;
		kfree(mem_search->next->address);		
		mem_delete=mem_search->next;
		mem_search->next=mem_search->next->next;
		kfree(mem_delete);
	}
	return 0;
}


int del_mem_list(void)
{
	struct mem_addr *mem_old;

#ifdef DEBUG_MEM
	DEBUGMSG("del_mem_list, mem_head=%p\n", mem_head);
	return 0;
#endif

	while (mem_head->next != NULL) {
		mem_old=mem_head;
		kfree(mem_old->address);
		mem_head=mem_old->next;
		kfree(mem_old);
	}
	
	return 0;
}

/* The function init_hw_struct is used to initialize the hardware structure. */
int init_hw_struct(void)
{
	int i=0;

	hardware_p->nr_boards=0;
	while ( (hw[i] != NULL) & (i < MAX_HW_CARDS) ) {
		hardware_p->nr_boards++;

		if (init_device_struct(i)) {
			CANMSG("Error initializing candevice_t structures.\n");
			return -ENODEV;
		}
		i++;
	}

	return 0;
}

/* The function init_device_struct is used to initialize a single device 
 * structure.
 */
int init_device_struct(int card)
{
	hardware_p->candevice[card]=(struct candevice_t *)kmalloc(sizeof(struct candevice_t),GFP_KERNEL);
	if (hardware_p->candevice[card]==NULL)
		return -ENOMEM;
	else
		if ( add_mem_to_list(hardware_p->candevice[card]) )
			return -ENOMEM;

	candevices_p[card]=hardware_p->candevice[card];

	hardware_p->candevice[card]->hwname=hw[card];
	hardware_p->candevice[card]->io_addr=io[card];

	hardware_p->candevice[card]->hwspecops=(struct hwspecops_t *)kmalloc(sizeof(struct hwspecops_t),GFP_KERNEL);
	if (hardware_p->candevice[card]->hwspecops==NULL)
		return -ENOMEM;
	else
		if ( add_mem_to_list(hardware_p->candevice[card]->hwspecops) )
			return -ENOMEM;

	if (init_hwspecops(card))
		return -ENODEV;

	if (candevices_p[card]->hwspecops->init_hw_data(card))
		return -ENODEV;

	if (init_chip_struct(card))
		return -ENODEV;

	return 0;
}

/* The function init_chip_struct is used to initialize all chip_t structures
 * on one hardware board.
 */
int init_chip_struct(int card)
{
	static int irq_count=0;
	int i=0;

	/* Alocate and initialize the chip structures */
	for (i=0; i nr_16c554_chips; i++) {
		candevices_p[card]->chip[i]=(struct chip_t *)kmalloc(sizeof(struct chip_t),GFP_KERNEL);
		if (candevices_p[card]->chip[i]==NULL)
			return -ENOMEM;
		else
			if ( add_mem_to_list(candevices_p[card]->chip[i]) )
				return -ENOMEM;

		candevices_p[card]->chip[i]->chipspecops=(struct chipspecops_t *)kmalloc(sizeof(struct chipspecops_t),GFP_KERNEL);
		if (candevices_p[card]->chip[i]->chipspecops==NULL)
			return -ENOMEM;
		else
			if ( add_mem_to_list(candevices_p[card]->chip[i]->chipspecops) )
				return -ENOMEM;

		chips_p[irq_count]=candevices_p[card]->chip[i];
		candevices_p[card]->chip[i]->hostdevice=candevices_p[card];
		candevices_p[card]->chip[i]->chip_irq=irq[irq_count];
		candevices_p[card]->chip[i]->flags=0x0;

		candevices_p[card]->hwspecops->init_chip_data(card,i);

		if (init_chipspecops(card,i))
			return -ENODEV;

		init_obj_struct(card, irq_count);

		irq_count++;
	} 

	return 0;
}

int init_obj_struct(int card, int chip)
{
	static int obj_count=0;
	int i=0,max_objects=0;

//	if (!strcmp(chips_p[chip]->chip_type,"i82527")) 
//		max_objects=15;
//	else
		max_objects=1;
	for (i=0; imsgobj[i]=(struct msgobj_t *)kmalloc(sizeof(struct msgobj_t),GFP_KERNEL);
		if (chips_p[chip]->msgobj[i] == NULL) 
			return -ENOMEM;
		else
			if ( add_mem_to_list(chips_p[chip]->msgobj[i]) )
				return -ENOMEM;

		chips_p[chip]->msgobj[i]->fifo=(struct canfifo_t *)kmalloc(sizeof(struct canfifo_t),GFP_KERNEL);
		if (chips_p[chip]->msgobj[i]->fifo == NULL)
			return -ENOMEM;
		else
			if ( add_mem_to_list(chips_p[chip]->msgobj[i]->fifo) )
				return -ENOMEM;
		
		if (minor[0] == -1) {
			objects_p[obj_count]=chips_p[chip]->msgobj[i];
			objects_p[obj_count]->hostchip=chips_p[chip];
			objects_p[obj_count]->object=i+1;
			objects_p[obj_count]->minor=obj_count;
		}
		else {
			objects_p[minor[chip]+i]=chips_p[chip]->msgobj[i];
			objects_p[minor[chip]+i]->hostchip=chips_p[chip];
			objects_p[minor[chip]+i]->object=i+1;
			objects_p[minor[chip]+i]->minor=minor[chip]+i;
		}

		chips_p[chip]->msgobj[i]->flags = 0x0;
	
		candevices_p[card]->hwspecops->init_obj_data(chip,i);

		obj_count++;
	}
	return 0;
}


int init_hwspecops(int card)
{

	#ifdef AIM104
	if (!strcmp(candevices_p[card]->hwname,"aim104")) {
		aim104_register(candevices_p[card]->hwspecops);
	}
	#endif

	return 0;
}

int init_chipspecops(int card, int chipnr)
{
	if (!strcmp(candevices_p[card]->chip[chipnr]->chip_type,"16c554")) {
		s16c554_register(candevices_p[card]->chip[chipnr]->chipspecops);
	}

	return 0;
}