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

📄 sdladrv.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 5 页
字号:
                }                 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 illegal!\n",				modname, virt_to_phys(hw->dpmbase));                        return -EINVAL;                }                               else if (sdla_setdpm(hw)) {                        printk(KERN_INFO			"%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. */#if defined(LINUX_2_1) || defined(LINUX_2_4)EXPORT_SYMBOL(sdla_down);#endifint 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];#if defined(LINUX_2_1) || defined(LINUX_2_4)		/* 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);#else                /* disable the PCI IRQ and disable memory access */             	pcibios_read_config_dword(hw->pci_bus, hw->pci_dev_func,			PCI_INT_CONFIG, &int_config);	        int_config &= (CPU_no == S514_CPU_A) ? ~PCI_DISABLE_IRQ_CPU_A :	~PCI_DISABLE_IRQ_CPU_B;        	pcibios_write_config_dword(hw->pci_bus, hw->pci_dev_func,			PCI_INT_CONFIG, int_config);                read_S514_int_stat(hw, &int_status);                S514_intack(hw, int_status);     		// disable PCI memory access		if(CPU_no == S514_CPU_A)	     		pcibios_write_config_dword(hw->pci_bus,hw->pci_dev_func,				PCI_MAP0_DWORD, PCI_CPU_A_MEM_DISABLE);		else                        pcibios_write_config_dword(hw->pci_bus,hw->pci_dev_func,							PCI_MAP1_DWORD, PCI_CPU_B_MEM_DISABLE);#endif		/* 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. */#if defined(LINUX_2_1) || defined(LINUX_2_4)EXPORT_SYMBOL(sdla_mapmem);#endifint 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. */#if defined(LINUX_2_1) || defined(LINUX_2_4)EXPORT_SYMBOL(sdla_inten);#endifint 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 defined(LINUX_2_1) || defined(LINUX_2_4)EXPORT_SYMBOL(sdla_intde);#endifint 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;}/*============================================================================ * Acknowledge SDLA hardware interrupt. */#if defined(LINUX_2_1) || defined(LINUX_2_4)EXPORT_SYMBOL(sdla_intack);#endifint 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. */#if defined(LINUX_2_1) || defined(LINUX_2_4)EXPORT_SYMBOL(S514_intack);#endifvoid S514_intack (sdlahw_t* hw, u32 int_status){#if defined(LINUX_2_1) || defined(LINUX_2_4)        pci_write_config_dword(hw->pci_dev, PCI_INT_STATUS, int_status);#else	pcibios_write_config_dword(hw->pci_bus, hw->pci_dev_func,                PCI_INT_STATUS, int_status);#endif}/*============================================================================ * Read the S514 hardware interrupt status. */#if defined(LINUX_2_1) || defined(LINUX_2_4)EXPORT_SYMBOL(read_S514_int_stat);#endifvoid read_S514_int_stat (sdlahw_t* hw, u32* int_status){#if defined(LINUX_2_1) || defined(LINUX_2_4)	pci_read_config_dword(hw->pci_dev, PCI_INT_STATUS, int_status);#else        pcibios_read_config_dword(hw->pci_bus, hw->pci_dev_func, PCI_INT_STATUS,		int_status);#endif}/*============================================================================ * Generate an interrupt to adapter's CPU. */#if defined(LINUX_2_1) || defined(LINUX_2_4)EXPORT_SYMBOL(sdla_intr);#endifint 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);		}

⌨️ 快捷键说明

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