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

📄 sdladrv.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************** sdladrv.c	SDLA Support Module.  Main module.**		This module is a library of common hardware-specific functions*		used by all Sangoma drivers.** Author:	Gideon Hack	** Copyright:	(c) 1995-2000 Sangoma Technologies Inc.**		This program is free software; you can redistribute it and/or*		modify it under the terms of the GNU General Public License*		as published by the Free Software Foundation; either version*		2 of the License, or (at your option) any later version.* ============================================================================* Mar 20, 2001  Nenad Corbic	Added the auto_pci_cfg filed, to support*                               the PCISLOT #0. * Apr 04, 2000  Nenad Corbic	Fixed the auto memory detection code.*                               The memory test at address 0xC8000.* Mar 09, 2000  Nenad Corbic 	Added Gideon's Bug Fix: clear pci*                               interrupt flags on initial load.* Jun 02, 1999  Gideon Hack     Added support for the S514 adapter.*				Updates for Linux 2.2.X kernels.	* Sep 17, 1998	Jaspreet Singh	Updates for linux 2.2.X kernels* Dec 20, 1996	Gene Kozin	Version 3.0.0. Complete overhaul.* Jul 12, 1996	Gene Kozin	Changes for Linux 2.0 compatibility.* Jun 12, 1996	Gene Kozin 	Added support for S503 card.* Apr 30, 1996	Gene Kozin	SDLA hardware interrupt is acknowledged before*				calling protocolspecific ISR.*				Register I/O ports with Linux kernel.*				Miscellaneous bug fixes.* Dec 20, 1995	Gene Kozin	Fixed a bug in interrupt routine.* Oct 14, 1995	Gene Kozin	Initial version.*****************************************************************************//***************************************************************************** * Notes: * ------ * 1. This code is ment to be system-independent (as much as possible).  To *    achive this, various macros are used to hide system-specific interfaces. *    To compile this code, one of the following constants must be defined: * *	Platform	Define *	--------	------ *	Linux		_LINUX_ *	SCO Unix	_SCO_UNIX_ * * 2. Supported adapter types: * *	S502A *	ES502A (S502E) *	S503 *	S507 *	S508 (S509) * * 3. S502A Notes: * *	There is no separate DPM window enable/disable control in S502A.  It *	opens immediately after a window number it written to the HMCR *	register.  To close the window, HMCR has to be written a value *	????1111b (e.g. 0x0F or 0xFF). * *	S502A DPM window cannot be located at offset E000 (e.g. 0xAE000). * *	There should be a delay of ??? before reading back S502A status *	register. * * 4. S502E Notes: * *	S502E has a h/w bug: although default IRQ line state is HIGH, enabling *	interrupts by setting bit 1 of the control register (BASE) to '1' *	causes it to go LOW! Therefore, disabling interrupts by setting that *	bit to '0' causes low-to-high transition on IRQ line (ghosty *	interrupt). The same occurs when disabling CPU by resetting bit 0 of *	CPU control register (BASE+3) - see the next note. * *	S502E CPU and DPM control is limited: * *	o CPU cannot be stopped independently. Resetting bit 0 of the CPUi *	  control register (BASE+3) shuts the board down entirely, including *	  DPM; * *	o DPM access cannot be controlled dynamically. Ones CPU is started, *	  bit 1 of the control register (BASE) is used to enable/disable IRQ, *	  so that access to shared memory cannot be disabled while CPU is *	  running. ****************************************************************************/#define	_LINUX_#if	defined(_LINUX_)	/****** Linux *******************************/#include <linux/config.h>#include <linux/kernel.h>	/* printk(), and other useful stuff */#include <linux/stddef.h>	/* offsetof(), etc. */#include <linux/errno.h>	/* return codes */#include <linux/string.h>	/* inline memset(), etc. */#include <linux/module.h>	/* support for loadable modules */#include <linux/jiffies.h>	/* for jiffies, HZ, etc. */#include <linux/sdladrv.h>	/* API definitions */#include <linux/sdlasfm.h>	/* SDLA firmware module definitions */#include <linux/sdlapci.h>	/* SDLA PCI hardware definitions */#include <linux/pci.h>		/* PCI defines and function prototypes */#include <asm/io.h>		/* for inb(), outb(), etc. */#define _INB(port)		(inb(port))#define _OUTB(port, byte)	(outb((byte),(port)))#define	SYSTEM_TICK		jiffies#include <linux/init.h>#elif	defined(_SCO_UNIX_)	/****** SCO Unix ****************************/#if	!defined(INKERNEL)#error	This code MUST be compiled in kernel mode!#endif#include <sys/sdladrv.h>	/* API definitions */#include <sys/sdlasfm.h>	/* SDLA firmware module definitions */#include <sys/inline.h>		/* for inb(), outb(), etc. */#define _INB(port)		(inb(port))#define _OUTB(port, byte)	(outb((port),(byte)))#define	SYSTEM_TICK		lbolt#else#error	Unknown system type!#endif#define	MOD_VERSION	3#define	MOD_RELEASE	0#define	SDLA_IODELAY	100	/* I/O Rd/Wr delay, 10 works for 486DX2-66 */#define	EXEC_DELAY	20	/* shared memory access delay, mks */#define	EXEC_TIMEOUT	(HZ*2)	/* command timeout, in ticks *//* I/O port address range */#define S502A_IORANGE	3#define S502E_IORANGE	4#define S503_IORANGE	3#define S507_IORANGE	4#define S508_IORANGE	4/* Maximum amount of memory */#define S502_MAXMEM	0x10000L#define S503_MAXMEM	0x10000L#define S507_MAXMEM	0x40000L#define S508_MAXMEM	0x40000L/* Minimum amount of memory */#define S502_MINMEM	0x8000L#define S503_MINMEM	0x8000L#define S507_MINMEM	0x20000L#define S508_MINMEM	0x20000L#define NO_PORT         -1/****** Function Prototypes *************************************************//* Hardware-specific functions */static int sdla_detect	(sdlahw_t* hw);static int sdla_autodpm	(sdlahw_t* hw);static int sdla_setdpm	(sdlahw_t* hw);static int sdla_load	(sdlahw_t* hw, sfm_t* sfm, unsigned len);static int sdla_init	(sdlahw_t* hw);static unsigned long sdla_memtest (sdlahw_t* hw);static int sdla_bootcfg	(sdlahw_t* hw, sfm_info_t* sfminfo);static unsigned char make_config_byte (sdlahw_t* hw);static int sdla_start	(sdlahw_t* hw, unsigned addr);static int init_s502a	(sdlahw_t* hw);static int init_s502e	(sdlahw_t* hw);static int init_s503	(sdlahw_t* hw);static int init_s507	(sdlahw_t* hw);static int init_s508	(sdlahw_t* hw);            static int detect_s502a	(int port);static int detect_s502e	(int port);static int detect_s503	(int port);static int detect_s507	(int port);static int detect_s508	(int port);static int detect_s514  (sdlahw_t* hw);static int find_s514_adapter(sdlahw_t* hw, char find_first_S514_card);/* Miscellaneous functions */static void peek_by_4 (unsigned long src, void* buf, unsigned len);static void poke_by_4 (unsigned long dest, void* buf, unsigned len);static int calibrate_delay (int mks);static int get_option_index (unsigned* optlist, unsigned optval);static unsigned check_memregion (void* ptr, unsigned len);static unsigned	test_memregion (void* ptr, unsigned len);static unsigned short checksum (unsigned char* buf, unsigned len);static int init_pci_slot(sdlahw_t *);static int pci_probe(sdlahw_t *hw);/****** Global Data ********************************************************** * Note: All data must be explicitly initialized!!! */static struct pci_device_id sdladrv_pci_tbl[] = {	{ V3_VENDOR_ID, V3_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, },	{ }			/* Terminating entry */};MODULE_DEVICE_TABLE(pci, sdladrv_pci_tbl);MODULE_LICENSE("GPL");/* private data */static char modname[]	= "sdladrv";static char fullname[]	= "SDLA Support Module";static char copyright[]	= "(c) 1995-1999 Sangoma Technologies Inc.";static unsigned	exec_idle;/* Hardware configuration options. * These are arrays of configuration options used by verification routines. * The first element of each array is its size (i.e. number of options). */static unsigned	s502_port_options[] =	{ 4, 0x250, 0x300, 0x350, 0x360 };static unsigned	s503_port_options[] =	{ 8, 0x250, 0x254, 0x300, 0x304, 0x350, 0x354, 0x360, 0x364 };static unsigned	s508_port_options[] =	{ 8, 0x250, 0x270, 0x280, 0x300, 0x350, 0x360, 0x380, 0x390 };static unsigned s502a_irq_options[] = { 0 };static unsigned s502e_irq_options[] = { 4, 2, 3, 5, 7 };static unsigned s503_irq_options[]  = { 5, 2, 3, 4, 5, 7 };static unsigned s508_irq_options[]  = { 8, 3, 4, 5, 7, 10, 11, 12, 15 };static unsigned s502a_dpmbase_options[] ={	28,	0xA0000, 0xA2000, 0xA4000, 0xA6000, 0xA8000, 0xAA000, 0xAC000,	0xC0000, 0xC2000, 0xC4000, 0xC6000, 0xC8000, 0xCA000, 0xCC000,	0xD0000, 0xD2000, 0xD4000, 0xD6000, 0xD8000, 0xDA000, 0xDC000,	0xE0000, 0xE2000, 0xE4000, 0xE6000, 0xE8000, 0xEA000, 0xEC000,};static unsigned s507_dpmbase_options[] ={	32,	0xA0000, 0xA2000, 0xA4000, 0xA6000, 0xA8000, 0xAA000, 0xAC000, 0xAE000,	0xB0000, 0xB2000, 0xB4000, 0xB6000, 0xB8000, 0xBA000, 0xBC000, 0xBE000,	0xC0000, 0xC2000, 0xC4000, 0xC6000, 0xC8000, 0xCA000, 0xCC000, 0xCE000,	0xE0000, 0xE2000, 0xE4000, 0xE6000, 0xE8000, 0xEA000, 0xEC000, 0xEE000,};static unsigned s508_dpmbase_options[] =	/* incl. S502E and S503 */{	32,	0xA0000, 0xA2000, 0xA4000, 0xA6000, 0xA8000, 0xAA000, 0xAC000, 0xAE000,	0xC0000, 0xC2000, 0xC4000, 0xC6000, 0xC8000, 0xCA000, 0xCC000, 0xCE000,	0xD0000, 0xD2000, 0xD4000, 0xD6000, 0xD8000, 0xDA000, 0xDC000, 0xDE000,	0xE0000, 0xE2000, 0xE4000, 0xE6000, 0xE8000, 0xEA000, 0xEC000, 0xEE000,};/*static unsigned	s502_dpmsize_options[] = { 2, 0x2000, 0x10000 };static unsigned	s507_dpmsize_options[] = { 2, 0x2000, 0x4000 };static unsigned	s508_dpmsize_options[] = { 1, 0x2000 };*/static unsigned	s502a_pclk_options[] = { 2, 3600, 7200 };static unsigned	s502e_pclk_options[] = { 5, 3600, 5000, 7200, 8000, 10000 };static unsigned	s503_pclk_options[]  = { 3, 7200, 8000, 10000 };static unsigned	s507_pclk_options[]  = { 1, 12288 };static unsigned	s508_pclk_options[]  = { 1, 16000 };/* Host memory control register masks */static unsigned char s502a_hmcr[] ={	0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C,	/* A0000 - AC000 */	0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x2C,	/* C0000 - CC000 */	0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C,	/* D0000 - DC000 */	0x30, 0x32, 0x34, 0x36, 0x38, 0x3A, 0x3C,	/* E0000 - EC000 */};static unsigned char s502e_hmcr[] ={	0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E,	/* A0000 - AE000 */	0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x2C, 0x2E,	/* C0000 - CE000 */	0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,	/* D0000 - DE000 */	0x30, 0x32, 0x34, 0x36, 0x38, 0x3A, 0x3C, 0x3E,	/* E0000 - EE000 */};static unsigned char s507_hmcr[] ={	0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,	/* A0000 - AE000 */	0x40, 0x42, 0x44, 0x46, 0x48, 0x4A, 0x4C, 0x4E,	/* B0000 - BE000 */	0x80, 0x82, 0x84, 0x86, 0x88, 0x8A, 0x8C, 0x8E,	/* C0000 - CE000 */	0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE,	/* E0000 - EE000 */};static unsigned char s508_hmcr[] ={	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,	/* A0000 - AE000 */	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,	/* C0000 - CE000 */	0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,	/* D0000 - DE000 */	0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,	/* E0000 - EE000 */};static unsigned char s507_irqmask[] ={	0x00, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xE0};static int pci_slot_ar[MAX_S514_CARDS];/******* Kernel Loadable Module Entry Points ********************************//*============================================================================ * Module 'insert' entry point. * o print announcement * o initialize static data * o calibrate SDLA shared memory access delay. * * Return:	0	Ok *		< 0	error. * Context:	process */static int __init sdladrv_init(void){	int i=0;	printk(KERN_INFO "%s v%u.%u %s\n",		fullname, MOD_VERSION, MOD_RELEASE, copyright);	exec_idle = calibrate_delay(EXEC_DELAY);#ifdef WANDEBUG		printk(KERN_DEBUG "%s: exec_idle = %d\n", modname, exec_idle);#endif		/* Initialize the PCI Card array, which         * will store flags, used to mark          * card initialization state */	for (i=0; i<MAX_S514_CARDS; i++)		pci_slot_ar[i] = 0xFF;	return 0;}/*============================================================================ * Module 'remove' entry point. * o release all remaining system resources */static void __exit sdladrv_cleanup(void){}module_init(sdladrv_init);module_exit(sdladrv_cleanup);/******* Kernel APIs ********************************************************//*============================================================================ * Set up adapter. * o detect adapter type * o verify hardware configuration options * o check for hardware conflicts * o set up adapter shared memory * o test adapter memory * o load firmware * Return:	0	ok. *		< 0	error */EXPORT_SYMBOL(sdla_setup);int sdla_setup (sdlahw_t* hw, void* sfm, unsigned len){	unsigned* irq_opt	= NULL;	/* IRQ options */	unsigned* dpmbase_opt	= NULL;	/* DPM window base options */	unsigned* pclk_opt	= NULL;	/* CPU clock rate options */	int err=0;	if (sdla_detect(hw)) {                if(hw->type != SDLA_S514)                        printk(KERN_INFO "%s: no SDLA card found at port 0x%X\n",                        modname, hw->port);		return -EINVAL;	}	if(hw->type != SDLA_S514) {                printk(KERN_INFO "%s: found S%04u card at port 0x%X.\n",                modname, hw->type, hw->port);                hw->dpmsize = SDLA_WINDOWSIZE;                switch (hw->type) {                case SDLA_S502A:                        hw->io_range    = S502A_IORANGE;                        irq_opt         = s502a_irq_options;                        dpmbase_opt     = s502a_dpmbase_options;                        pclk_opt        = s502a_pclk_options;                        break;                case SDLA_S502E:                        hw->io_range    = S502E_IORANGE;                        irq_opt         = s502e_irq_options;                        dpmbase_opt     = s508_dpmbase_options;                        pclk_opt        = s502e_pclk_options;                        break;                case SDLA_S503:                        hw->io_range    = S503_IORANGE;                        irq_opt         = s503_irq_options;                        dpmbase_opt     = s508_dpmbase_options;                        pclk_opt        = s503_pclk_options;                        break;                case SDLA_S507:                        hw->io_range    = S507_IORANGE;                        irq_opt         = s508_irq_options;                        dpmbase_opt     = s507_dpmbase_options;                        pclk_opt        = s507_pclk_options;                        break;                case SDLA_S508:                        hw->io_range    = S508_IORANGE;                        irq_opt         = s508_irq_options;                        dpmbase_opt     = s508_dpmbase_options;                        pclk_opt        = s508_pclk_options;                        break;                }                /* Verify IRQ configuration options */                if (!get_option_index(irq_opt, hw->irq)) {                        printk(KERN_INFO "%s: IRQ %d is invalid!\n",                        	modname, hw->irq);                      return -EINVAL;                }                 /* Verify CPU clock rate configuration options */                if (hw->pclk == 0)                        hw->pclk = pclk_opt[1];  /* use default */                        else if (!get_option_index(pclk_opt, hw->pclk)) {                        printk(KERN_INFO "%s: CPU clock %u is invalid!\n",				modname, hw->pclk);                        return -EINVAL;                }                 printk(KERN_INFO "%s: assuming CPU clock rate of %u kHz.\n",			modname, hw->pclk);                /* Setup adapter dual-port memory window and test memory */                if (hw->dpmbase == 0) {                        err = sdla_autodpm(hw);                        if (err) {                                printk(KERN_INFO				"%s: can't find available memory region!\n",					modname);                                return err;                        }                }                else if (!get_option_index(dpmbase_opt,			virt_to_phys(hw->dpmbase))) {                        printk(KERN_INFO				"%s: memory address 0x%lX is invalid!\n",				modname, virt_to_phys(hw->dpmbase));                        return -EINVAL;                }                               else if (sdla_setdpm(hw)) {                        printk(KERN_INFO

⌨️ 快捷键说明

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