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

📄 sdladrv.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
			"%s: 8K memory region at 0x%lX is not available!\n",				modname, virt_to_phys(hw->dpmbase));                        return -EINVAL;                }                 printk(KERN_INFO			"%s: dual-port memory window is set at 0x%lX.\n",				modname, virt_to_phys(hw->dpmbase));		/* If we find memory in 0xE**** Memory region,                  * warn the user to disable the SHADOW RAM.                   * Since memory corruption can occur if SHADOW is                 * enabled. This can causes random crashes ! */		if (virt_to_phys(hw->dpmbase) >= 0xE0000){			printk(KERN_WARNING "\n%s: !!!!!!!!  WARNING !!!!!!!!\n",modname);			printk(KERN_WARNING "%s: WANPIPE is using 0x%lX memory region !!!\n",						modname, virt_to_phys(hw->dpmbase));			printk(KERN_WARNING "         Please disable the SHADOW RAM, otherwise\n");			printk(KERN_WARNING "         your system might crash randomly from time to time !\n");			printk(KERN_WARNING "%s: !!!!!!!!  WARNING !!!!!!!!\n\n",modname);		}        }	else {		hw->memory = test_memregion((void*)hw->dpmbase, 			MAX_SIZEOF_S514_MEMORY);		if(hw->memory < (256 * 1024)) {			printk(KERN_INFO				"%s: error in testing S514 memory (0x%lX)\n",				modname, hw->memory);			sdla_down(hw);			return -EINVAL;		}	}    	printk(KERN_INFO "%s: found %luK bytes of on-board memory\n",		modname, hw->memory / 1024);	/* Load firmware. If loader fails then shut down adapter */	err = sdla_load(hw, sfm, len);	if (err) sdla_down(hw);		/* shutdown adapter */	return err;} /*============================================================================ * Shut down SDLA: disable shared memory access and interrupts, stop CPU, etc. */EXPORT_SYMBOL(sdla_down);int sdla_down (sdlahw_t* hw){	unsigned port = hw->port;	int i;        unsigned char CPU_no;        u32 int_config, int_status;        if(!port && (hw->type != SDLA_S514))                return -EFAULT;	switch (hw->type) {	case SDLA_S502A:		_OUTB(port, 0x08);		/* halt CPU */		_OUTB(port, 0x08);		_OUTB(port, 0x08);		hw->regs[0] = 0x08;		_OUTB(port + 1, 0xFF);		/* close memory window */		hw->regs[1] = 0xFF;		break;	case SDLA_S502E:		_OUTB(port + 3, 0);		/* stop CPU */		_OUTB(port, 0);			/* reset board */		for (i = 0; i < S502E_IORANGE; ++i)			hw->regs[i] = 0		;		break;	case SDLA_S503:	case SDLA_S507:	case SDLA_S508:		_OUTB(port, 0);			/* reset board logic */		hw->regs[0] = 0;		break;	case SDLA_S514:		/* halt the adapter */                *(char *)hw->vector = S514_CPU_HALT;        	CPU_no = hw->S514_cpu_no[0];		/* disable the PCI IRQ and disable memory access */                pci_read_config_dword(hw->pci_dev, PCI_INT_CONFIG, &int_config);	        int_config &= (CPU_no == S514_CPU_A) ? ~PCI_DISABLE_IRQ_CPU_A :	~PCI_DISABLE_IRQ_CPU_B;                pci_write_config_dword(hw->pci_dev, PCI_INT_CONFIG, int_config);		read_S514_int_stat(hw, &int_status);		S514_intack(hw, int_status);		if(CPU_no == S514_CPU_A)                        pci_write_config_dword(hw->pci_dev, PCI_MAP0_DWORD,				PCI_CPU_A_MEM_DISABLE);		else                        pci_write_config_dword(hw->pci_dev, PCI_MAP1_DWORD,				PCI_CPU_B_MEM_DISABLE);		/* free up the allocated virtual memory */ 		iounmap((void *)hw->dpmbase);        	iounmap((void *)hw->vector); 		break;	default:		return -EINVAL;	}	return 0;}/*============================================================================ * Map shared memory window into SDLA address space. */EXPORT_SYMBOL(sdla_mapmem);int sdla_mapmem (sdlahw_t* hw, unsigned long addr){	unsigned port = hw->port;	register int tmp;	switch (hw->type) {	case SDLA_S502A:	case SDLA_S502E:		if (addr < S502_MAXMEM)	{ /* verify parameter */			tmp = addr >> 13;	/* convert to register mask */			_OUTB(port + 2, tmp);			hw->regs[2] = tmp;		}		else return -EINVAL;		break;	case SDLA_S503:		if (addr < S503_MAXMEM)	{ /* verify parameter */			tmp = (hw->regs[0] & 0x8F) | ((addr >> 9) & 0x70);			_OUTB(port, tmp);			hw->regs[0] = tmp;		}		else return -EINVAL;		break;	case SDLA_S507:		if (addr < S507_MAXMEM) {			if (!(_INB(port) & 0x02))				return -EIO;			tmp = addr >> 13;	/* convert to register mask */			_OUTB(port + 2, tmp);			hw->regs[2] = tmp;		}		else return -EINVAL;		break;	case SDLA_S508:		if (addr < S508_MAXMEM) {			tmp = addr >> 13;	/* convert to register mask */			_OUTB(port + 2, tmp);			hw->regs[2] = tmp;		}		else return -EINVAL;		break;	case SDLA_S514:		return 0; 	default:		return -EINVAL;	}	hw->vector = addr & 0xFFFFE000L;	return 0;}/*============================================================================ * Enable interrupt generation. */static int sdla_inten (sdlahw_t* hw){	unsigned port = hw->port;	int tmp, i;	switch (hw->type) {	case SDLA_S502E:		/* Note thar interrupt control operations on S502E are allowed		 * only if CPU is enabled (bit 0 of status register is set).		 */		if (_INB(port) & 0x01) {			_OUTB(port, 0x02);	/* bit1 = 1, bit2 = 0 */			_OUTB(port, 0x06);	/* bit1 = 1, bit2 = 1 */			hw->regs[0] = 0x06;		}		else return -EIO;		break;	case SDLA_S503:		tmp = hw->regs[0] | 0x04;		_OUTB(port, tmp);		hw->regs[0] = tmp;		/* update mirror */		for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */		if (!(_INB(port) & 0x02))		/* verify */			return -EIO;		break;	case SDLA_S508:		tmp = hw->regs[0] | 0x10;		_OUTB(port, tmp);		hw->regs[0] = tmp;		/* update mirror */		for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */		if (!(_INB(port + 1) & 0x10))		/* verify */			return -EIO;		break;	case SDLA_S502A:	case SDLA_S507:		break;        case SDLA_S514:                break;	default:		return -EINVAL;	}	return 0;}/*============================================================================ * Disable interrupt generation. */#if 0int sdla_intde (sdlahw_t* hw){	unsigned port = hw->port;	int tmp, i;	switch (hw->type) {	case SDLA_S502E:		/* Notes:		 *  1) interrupt control operations are allowed only if CPU is		 *     enabled (bit 0 of status register is set).		 *  2) disabling interrupts using bit 1 of control register		 *     causes IRQ line go high, therefore we are going to use		 *     0x04 instead: lower it to inhibit interrupts to PC.		 */		if (_INB(port) & 0x01) {			_OUTB(port, hw->regs[0] & ~0x04);			hw->regs[0] &= ~0x04;		}		else return -EIO;		break;	case SDLA_S503:		tmp = hw->regs[0] & ~0x04;		_OUTB(port, tmp);		hw->regs[0] = tmp;			/* update mirror */		for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */		if (_INB(port) & 0x02)			/* verify */			return -EIO;		break;	case SDLA_S508:		tmp = hw->regs[0] & ~0x10;		_OUTB(port, tmp);		hw->regs[0] = tmp;			/* update mirror */		for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */		if (_INB(port) & 0x10)			/* verify */			return -EIO;		break;	case SDLA_S502A:	case SDLA_S507:		break;	default:		return -EINVAL;	}	return 0;}#endif  /*  0  *//*============================================================================ * Acknowledge SDLA hardware interrupt. */static int sdla_intack (sdlahw_t* hw){	unsigned port = hw->port;	int tmp;	switch (hw->type) {	case SDLA_S502E:		/* To acknoledge hardware interrupt we have to toggle bit 3 of		 * control register: \_/		 * Note that interrupt control operations on S502E are allowed		 * only if CPU is enabled (bit 1 of status register is set).		 */		if (_INB(port) & 0x01) {			tmp = hw->regs[0] & ~0x04;			_OUTB(port, tmp);			tmp |= 0x04;			_OUTB(port, tmp);			hw->regs[0] = tmp;		}		else return -EIO;		break;	case SDLA_S503:		if (_INB(port) & 0x04) {			tmp = hw->regs[0] & ~0x08;			_OUTB(port, tmp);			tmp |= 0x08;			_OUTB(port, tmp);			hw->regs[0] = tmp;		}		break;	case SDLA_S502A:	case SDLA_S507:	case SDLA_S508:	break;	default:		return -EINVAL;	}	return 0;}/*============================================================================ * Acknowledge S514 hardware interrupt. */EXPORT_SYMBOL(S514_intack);void S514_intack (sdlahw_t* hw, u32 int_status){        pci_write_config_dword(hw->pci_dev, PCI_INT_STATUS, int_status);}/*============================================================================ * Read the S514 hardware interrupt status. */EXPORT_SYMBOL(read_S514_int_stat);void read_S514_int_stat (sdlahw_t* hw, u32* int_status){	pci_read_config_dword(hw->pci_dev, PCI_INT_STATUS, int_status);}/*============================================================================ * Generate an interrupt to adapter's CPU. */#if 0int sdla_intr (sdlahw_t* hw){	unsigned port = hw->port;	switch (hw->type) {	case SDLA_S502A:		if (!(_INB(port) & 0x40)) {			_OUTB(port, 0x10);		/* issue NMI to CPU */			hw->regs[0] = 0x10;		}		else return -EIO;		break;	case SDLA_S507:		if ((_INB(port) & 0x06) == 0x06) {			_OUTB(port + 3, 0);		}		else return -EIO;		break;	case SDLA_S508:		if (_INB(port + 1) & 0x02) {			_OUTB(port, 0x08);		}		else return -EIO;		break;	case SDLA_S502E:	case SDLA_S503:	default:		return -EINVAL;	}	return 0;}#endif  /*  0  *//*============================================================================ * Execute Adapter Command. * o Set exec flag. * o Busy-wait until flag is reset. * o Return number of loops made, or 0 if command timed out. */EXPORT_SYMBOL(sdla_exec);int sdla_exec (void* opflag){	volatile unsigned char* flag = opflag;	unsigned long tstop;	int nloops;	if(readb(flag) != 0x00) {		printk(KERN_INFO			"WANPIPE: opp flag set on entry to sdla_exec\n");		return 0;	}		writeb(0x01, flag);	tstop = SYSTEM_TICK + EXEC_TIMEOUT;	for (nloops = 1; (readb(flag) == 0x01); ++ nloops) {		unsigned delay = exec_idle;		while (-- delay);			/* delay */		if (SYSTEM_TICK > tstop) return 0;	/* time is up! */	}	return nloops;}/*============================================================================ * Read absolute adapter memory. * Transfer data from adapter's memory to data buffer. * * Note: * Care should be taken when crossing dual-port memory window boundary. * This function is not atomic, so caller must disable interrupt if * interrupt routines are accessing adapter shared memory. */EXPORT_SYMBOL(sdla_peek);int sdla_peek (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len){	if (addr + len > hw->memory)	/* verify arguments */		return -EINVAL;        if(hw->type == SDLA_S514) {	/* copy data for the S514 adapter */                peek_by_4 ((unsigned long)hw->dpmbase + addr, buf, len);                return 0;	}        else {				/* copy data for the S508 adapter */	        unsigned long oldvec = hw->vector;        	unsigned winsize = hw->dpmsize;	        unsigned curpos, curlen;   /* current offset and block size */        	unsigned long curvec;      /* current DPM window vector */	        int err = 0;                while (len && !err) {

⌨️ 快捷键说明

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