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

📄 sdladrv.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
 *	1. After writing 0x00 to control register, status register should read *	   ??000000b. *	2. After writing 0x10 to control register, status register should read *	   ??010000b *	Return 1 if detected o.k. or 0 if failed. *	Note:	This test is destructive! Adapter will be left in shutdown *		state after the test. */static int detect_s508 (int port){	int i;	if (!get_option_index(s508_port_options, port))		return 0;	_OUTB(port, 0x00);	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */	if ((_INB(port + 1) & 0x3F) != 0x00)		return 0;	_OUTB(port, 0x10);	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */	if ((_INB(port + 1) & 0x3F) != 0x10)		return 0;	/* Reset adapter */	_OUTB(port, 0x00);	return 1;}/*============================================================================ * Detect s514 PCI adapter. *      Return 1 if detected o.k. or 0 if failed. *      Note:   This test is destructive! Adapter will be left in shutdown *              state after the test. */static int detect_s514 (sdlahw_t* hw){	unsigned char CPU_no, slot_no, auto_slot_cfg;	int number_S514_cards = 0;	u32 S514_mem_base_addr = 0;	u32 ut_u32;	struct pci_dev *pci_dev;#ifndef CONFIG_PCI        printk(KERN_INFO "%s: Linux not compiled for PCI usage!\n", modname);        return 0;#endif	/*	The 'setup()' procedure in 'sdlamain.c' passes the CPU number and the	slot number defined in 'router.conf' via the 'port' definition.	*/	CPU_no = hw->S514_cpu_no[0];	slot_no = hw->S514_slot_no;	auto_slot_cfg = hw->auto_pci_cfg;	if (auto_slot_cfg){		printk(KERN_INFO "%s: srch... S514 card, CPU %c, Slot=Auto\n",		modname, CPU_no);	}else{		printk(KERN_INFO "%s: srch... S514 card, CPU %c, Slot #%d\n",		modname, CPU_no, slot_no);	}		/* check to see that CPU A or B has been selected in 'router.conf' */	switch(CPU_no) {		case S514_CPU_A:		case S514_CPU_B:			break;			default:			printk(KERN_INFO "%s: S514 CPU definition invalid.\n", 				modname);			printk(KERN_INFO "Must be 'A' or 'B'\n");			return 0;	}	number_S514_cards = find_s514_adapter(hw, 0);	if(!number_S514_cards)		return 0;	/* we are using a single S514 adapter with a slot of 0 so re-read the */		/* location of this adapter */	if((number_S514_cards == 1) && auto_slot_cfg) {	        	number_S514_cards = find_s514_adapter(hw, 1);		if(!number_S514_cards) {			printk(KERN_INFO "%s: Error finding PCI card\n",				modname);			return 0;		}	}	pci_dev = hw->pci_dev;	/* read the physical memory base address */	S514_mem_base_addr = (CPU_no == S514_CPU_A) ? 		(pci_dev->resource[1].start) :		(pci_dev->resource[2].start);		printk(KERN_INFO "%s: S514 PCI memory at 0x%X\n",		modname, S514_mem_base_addr);	if(!S514_mem_base_addr) {		if(CPU_no == S514_CPU_B)			printk(KERN_INFO "%s: CPU #B not present on the card\n", 				modname);		else			printk(KERN_INFO "%s: No PCI memory allocated to card\n",				modname);		return 0;	}	/* enable the PCI memory */	pci_read_config_dword(pci_dev, 		(CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD,		&ut_u32);	pci_write_config_dword(pci_dev,		(CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD,		(ut_u32 | PCI_MEMORY_ENABLE));	/* check the IRQ allocated and enable IRQ usage */	if(!(hw->irq = pci_dev->irq)) {		printk(KERN_INFO "%s: IRQ not allocated to S514 adapter\n",			modname);                return 0;	}	/* BUG FIX : Mar 6 2000 	 * On a initial loading of the card, we must check         * and clear PCI interrupt bits, due to a reset         * problem on some other boards.  i.e. An interrupt         * might be pending, even after system bootup,          * in which case, when starting wanrouter the machine         * would crash. 	 */	if (init_pci_slot(hw))		return 0;        pci_read_config_dword(pci_dev, PCI_INT_CONFIG, &ut_u32);        ut_u32 |= (CPU_no == S514_CPU_A) ?                PCI_ENABLE_IRQ_CPU_A : PCI_ENABLE_IRQ_CPU_B;        pci_write_config_dword(pci_dev, PCI_INT_CONFIG, ut_u32);	printk(KERN_INFO "%s: IRQ %d allocated to the S514 card\n",		modname, hw->irq);	/* map the physical PCI memory to virtual memory */	hw->dpmbase = ioremap((unsigned long)S514_mem_base_addr,		(unsigned long)MAX_SIZEOF_S514_MEMORY);    	/* map the physical control register memory to virtual memory */	hw->vector = (unsigned long)ioremap(		(unsigned long)(S514_mem_base_addr + S514_CTRL_REG_BYTE),		(unsigned long)16);             if(!hw->dpmbase || !hw->vector) {		printk(KERN_INFO "%s: PCI virtual memory allocation failed\n",			modname);                return 0;	}	/* halt the adapter */	writeb (S514_CPU_HALT, hw->vector);		return 1;}/*============================================================================ * Find the S514 PCI adapter in the PCI bus. *      Return the number of S514 adapters found (0 if no adapter found). */static int find_s514_adapter(sdlahw_t* hw, char find_first_S514_card){        unsigned char slot_no;        int number_S514_cards = 0;	char S514_found_in_slot = 0;        u16 PCI_subsys_vendor;        struct pci_dev *pci_dev = NULL;        slot_no = hw->S514_slot_no;  	while ((pci_dev = pci_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_dev))        	!= NULL) {                		pci_read_config_word(pci_dev, PCI_SUBSYS_VENDOR_WORD,                        &PCI_subsys_vendor);                		if(PCI_subsys_vendor != SANGOMA_SUBSYS_VENDOR)                	continue;        			hw->pci_dev = pci_dev;				if(find_first_S514_card)			return(1);		                number_S514_cards ++;                		printk(KERN_INFO			"%s: S514 card found, slot #%d (devfn 0x%X)\n",                        modname, ((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK),			pci_dev->devfn);				if (hw->auto_pci_cfg){			hw->S514_slot_no = ((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK);			slot_no = hw->S514_slot_no;					}else if (((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK) == slot_no){                        S514_found_in_slot = 1;                        break;                }        }	/* if no S514 adapter has been found, then exit */        if (!number_S514_cards) {                printk(KERN_INFO "%s: Error, no S514 adapters found\n", modname);                return 0;        }        /* if more than one S514 card has been found, then the user must have */        /* defined a slot number so that the correct adapter is used */        else if ((number_S514_cards > 1) && hw->auto_pci_cfg) {                printk(KERN_INFO "%s: Error, PCI Slot autodetect Failed! \n"				 "%s:        More than one S514 adapter found.\n"				 "%s:        Disable the Autodetect feature and supply\n"				 "%s:        the PCISLOT numbers for each card.\n",                        modname,modname,modname,modname);                return 0;        }        /* if the user has specified a slot number and the S514 adapter has */        /* not been found in that slot, then exit */        else if (!hw->auto_pci_cfg && !S514_found_in_slot) {                printk(KERN_INFO			"%s: Error, S514 card not found in specified slot #%d\n",                        modname, slot_no);                return 0;        }	return (number_S514_cards);}/******* Miscellaneous ******************************************************//*============================================================================ * Calibrate SDLA memory access delay. * Count number of idle loops made within 1 second and then calculate the * number of loops that should be made to achive desired delay. */static int calibrate_delay (int mks){	unsigned int delay;	unsigned long stop;	for (delay = 0, stop = SYSTEM_TICK + HZ; SYSTEM_TICK < stop; ++delay);	return (delay/(1000000L/mks) + 1);}/*============================================================================ * Get option's index into the options list. *	Return option's index (1 .. N) or zero if option is invalid. */static int get_option_index (unsigned* optlist, unsigned optval){	int i;	for (i = 1; i <= optlist[0]; ++i)		if ( optlist[i] == optval)			return i;	return 0;}/*============================================================================ * Check memory region to see if it's available.  * Return:	0	ok. */static unsigned check_memregion (void* ptr, unsigned len){	volatile unsigned char* p = ptr;        for (; len && (readb (p) == 0xFF); --len, ++p) {                writeb (0, p);          /* attempt to write 0 */                if (readb(p) != 0xFF) { /* still has to read 0xFF */                        writeb (0xFF, p);/* restore original value */                        break;          /* not good */                }        }	return len;}/*============================================================================ * Test memory region. * Return:	size of the region that passed the test. * Note:	Region size must be multiple of 2 ! */static unsigned test_memregion (void* ptr, unsigned len){	volatile unsigned short* w_ptr;	unsigned len_w = len >> 1;	/* region len in words */	unsigned i;        for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)                writew (0xAA55, w_ptr);        	for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)                if (readw (w_ptr) != 0xAA55) {                        len_w = i;                        break;                }        for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)                writew (0x55AA, w_ptr);                for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)                if (readw(w_ptr) != 0x55AA) {                        len_w = i;                        break;                }                for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)		writew (0, w_ptr);        return len_w << 1;}/*============================================================================ * Calculate 16-bit CRC using CCITT polynomial. */static unsigned short checksum (unsigned char* buf, unsigned len){	unsigned short crc = 0;	unsigned mask, flag;	for (; len; --len, ++buf) {		for (mask = 0x80; mask; mask >>= 1) {			flag = (crc & 0x8000);			crc <<= 1;			crc |= ((*buf & mask) ? 1 : 0);			if (flag) crc ^= 0x1021;		}	}	return crc;}static int init_pci_slot(sdlahw_t *hw){	u32 int_status;	int volatile found=0;	int i=0;	/* Check if this is a very first load for a specific         * pci card. If it is, clear the interrput bits, and         * set the flag indicating that this card was initialized.	 */		for (i=0; (i<MAX_S514_CARDS) && !found; i++){		if (pci_slot_ar[i] == hw->S514_slot_no){			found=1;			break;		}		if (pci_slot_ar[i] == 0xFF){			break;		}	}	if (!found){		read_S514_int_stat(hw,&int_status);		S514_intack(hw,int_status);		if (i == MAX_S514_CARDS){			printk(KERN_INFO "%s: Critical Error !!!\n",modname);			printk(KERN_INFO 				"%s: Number of Sangoma PCI cards exceeded maximum limit.\n",					modname);			printk(KERN_INFO "Please contact Sangoma Technologies\n");			return 1;		}		pci_slot_ar[i] = hw->S514_slot_no;	}	return 0;}static int pci_probe(sdlahw_t *hw){        unsigned char slot_no;        int number_S514_cards = 0;        u16 PCI_subsys_vendor;	u16 PCI_card_type;        struct pci_dev *pci_dev = NULL;	struct pci_bus *bus = NULL;        slot_no = 0;  	while ((pci_dev = pci_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_dev))        	!= NULL) {		                pci_read_config_word(pci_dev, PCI_SUBSYS_VENDOR_WORD,                        &PCI_subsys_vendor);		                if(PCI_subsys_vendor != SANGOMA_SUBSYS_VENDOR)                	continue;		pci_read_config_word(pci_dev, PCI_CARD_TYPE,                        &PCI_card_type);			bus = pci_dev->bus;				/* A dual cpu card can support up to 4 physical connections,		 * where a single cpu card can support up to 2 physical		 * connections.  The FT1 card can only support a single 		 * connection, however we cannot distinguish between a Single		 * CPU card and an FT1 card. */		if (PCI_card_type == S514_DUAL_CPU){                	number_S514_cards += 4;			 printk(KERN_INFO				"wanpipe: S514-PCI card found, cpu(s) 2, bus #%d, slot #%d, irq #%d\n",                        	bus->number,((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK),				pci_dev->irq);		}else{			number_S514_cards += 2;			printk(KERN_INFO				"wanpipe: S514-PCI card found, cpu(s) 1, bus #%d, slot #%d, irq #%d\n",                        	bus->number,((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK),				pci_dev->irq);		}        }	return number_S514_cards;}EXPORT_SYMBOL(wanpipe_hw_probe);unsigned wanpipe_hw_probe(void){	sdlahw_t hw;	unsigned* opt = s508_port_options; 	unsigned cardno=0;	int i;		memset(&hw, 0, sizeof(hw));		for (i = 1; i <= opt[0]; i++) {		if (detect_s508(opt[i])){			/* S508 card can support up to two physical links */			cardno+=2;			printk(KERN_INFO "wanpipe: S508-ISA card found, port 0x%x\n",opt[i]);		}	}      #ifdef CONFIG_PCI	hw.S514_slot_no = 0;	cardno += pci_probe(&hw);      #else	printk(KERN_INFO "wanpipe: Warning, Kernel not compiled for PCI support!\n");	printk(KERN_INFO "wanpipe: PCI Hardware Probe Failed!\n");      #endif	return cardno;}/****** End *****************************************************************/

⌨️ 快捷键说明

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