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

📄 sdladrv.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 5 页
字号:
/*============================================================================ * Test adapter on-board memory. * o slide DPM window from the bottom up and test adapter memory segment by *   segment. * Return adapter memory size. */static unsigned long sdla_memtest (sdlahw_t* hw){	unsigned long memsize;	unsigned winsize;	for (memsize = 0, winsize = hw->dpmsize;	     !sdla_mapmem(hw, memsize) &&		(test_memregion(hw->dpmbase, winsize) == winsize)	     ;	     memsize += winsize)	;	hw->memory = memsize;	return memsize;}/*============================================================================ * Prepare boot-time firmware configuration data. * o position DPM window * o initialize configuration data area */static int sdla_bootcfg (sdlahw_t* hw, sfm_info_t* sfminfo){	unsigned char* data;	if (!sfminfo->datasize) return 0;	/* nothing to do */	if (sdla_mapmem(hw, sfminfo->dataoffs) != 0)		return -EIO;	if(hw->type == SDLA_S514)                data = (void*)(hw->dpmbase + sfminfo->dataoffs);        else                data = (void*)((u8 *)hw->dpmbase +                        (sfminfo->dataoffs - hw->vector));	memset_io (data, 0, sfminfo->datasize);	writeb (make_config_byte(hw), &data[0x00]);	switch (sfminfo->codeid) {	case SFID_X25_502:	case SFID_X25_508:                writeb (3, &data[0x01]);        /* T1 timer */                writeb (10, &data[0x03]);       /* N2 */                writeb (7, &data[0x06]);        /* HDLC window size */                writeb (1, &data[0x0B]);        /* DTE */                writeb (2, &data[0x0C]);        /* X.25 packet window size */                writew (128, &data[0x0D]);	/* default X.25 data size */                writew (128, &data[0x0F]);	/* maximum X.25 data size */		break;	}	return 0;}/*============================================================================ * Prepare configuration byte identifying adapter type and CPU clock rate. */static unsigned char make_config_byte (sdlahw_t* hw){	unsigned char byte = 0;	switch (hw->pclk) {		case 5000:  byte = 0x01; break;		case 7200:  byte = 0x02; break;		case 8000:  byte = 0x03; break;		case 10000: byte = 0x04; break;		case 16000: byte = 0x05; break;	}	switch (hw->type) {		case SDLA_S502E: byte |= 0x80; break;		case SDLA_S503:  byte |= 0x40; break;	}	return byte;}/*============================================================================ * Start adapter's CPU. * o calculate a pointer to adapter's cold boot entry point * o position DPM window * o place boot instruction (jp addr) at cold boot entry point * o start CPU */static int sdla_start (sdlahw_t* hw, unsigned addr){	unsigned port = hw->port;	unsigned char *bootp;	int err, tmp, i;	if (!port && (hw->type != SDLA_S514)) return -EFAULT; 	switch (hw->type) {	case SDLA_S502A:		bootp = hw->dpmbase;		bootp += 0x66;		break;	case SDLA_S502E:	case SDLA_S503:	case SDLA_S507:	case SDLA_S508:	case SDLA_S514:		bootp = hw->dpmbase;		break;	default:		return -EINVAL;	}	err = sdla_mapmem(hw, 0);	if (err) return err;      	writeb (0xC3, bootp);   /* Z80: 'jp' opcode */	bootp ++;	writew (addr, bootp);	switch (hw->type) {	case SDLA_S502A:		_OUTB(port, 0x10);		/* issue NMI to CPU */		hw->regs[0] = 0x10;		break;	case SDLA_S502E:		_OUTB(port + 3, 0x01);		/* start CPU */		hw->regs[3] = 0x01;		for (i = 0; i < SDLA_IODELAY; ++i);		if (_INB(port) & 0x01) {	/* verify */			/*			 * Enabling CPU changes functionality of the			 * control register, so we have to reset its			 * mirror.			 */			_OUTB(port, 0);		/* disable interrupts */			hw->regs[0] = 0;		}		else return -EIO;		break;	case SDLA_S503:		tmp = hw->regs[0] | 0x09;	/* set bits 0 and 3 */		_OUTB(port, tmp);		hw->regs[0] = tmp;		/* update mirror */		for (i = 0; i < SDLA_IODELAY; ++i);		if (!(_INB(port) & 0x01))	/* verify */			return -EIO;		break;	case SDLA_S507:		tmp = hw->regs[0] | 0x02;		_OUTB(port, tmp);		hw->regs[0] = tmp;		/* update mirror */		for (i = 0; i < SDLA_IODELAY; ++i);		if (!(_INB(port) & 0x04))	/* verify */			return -EIO;		break;	case SDLA_S508:		tmp = hw->regs[0] | 0x02;		_OUTB(port, tmp);		hw->regs[0] = tmp;	/* update mirror */		for (i = 0; i < SDLA_IODELAY; ++i);		if (!(_INB(port + 1) & 0x02))	/* verify */			return -EIO;		break;	case SDLA_S514:		writeb (S514_CPU_START, hw->vector);		break;	default:		return -EINVAL;	}	return 0;}/*============================================================================ * Initialize S502A adapter. */static int init_s502a (sdlahw_t* hw){	unsigned port = hw->port;	int tmp, i;	if (!detect_s502a(port))		return -ENODEV;	hw->regs[0] = 0x08;	hw->regs[1] = 0xFF;	/* Verify configuration options */	i = get_option_index(s502a_dpmbase_options, virt_to_phys(hw->dpmbase));	if (i == 0)		return -EINVAL;	tmp = s502a_hmcr[i - 1];	switch (hw->dpmsize) {	case 0x2000:		tmp |= 0x01;		break;	case 0x10000L:		break;	default:		return -EINVAL;	}	/* Setup dual-port memory window (this also enables memory access) */	_OUTB(port + 1, tmp);	hw->regs[1] = tmp;	hw->regs[0] = 0x08;	return 0;}/*============================================================================ * Initialize S502E adapter. */static int init_s502e (sdlahw_t* hw){	unsigned port = hw->port;	int tmp, i;	if (!detect_s502e(port))		return -ENODEV;	/* Verify configuration options */	i = get_option_index(s508_dpmbase_options, virt_to_phys(hw->dpmbase));	if (i == 0)		return -EINVAL;	tmp = s502e_hmcr[i - 1];	switch (hw->dpmsize) {	case 0x2000:		tmp |= 0x01;		break;	case 0x10000L:		break;	default:		return -EINVAL;	}	/* Setup dual-port memory window */	_OUTB(port + 1, tmp);	hw->regs[1] = tmp;	/* Enable memory access */	_OUTB(port, 0x02);	hw->regs[0] = 0x02;	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */	return (_INB(port) & 0x02) ? 0 : -EIO;}/*============================================================================ * Initialize S503 adapter. * --------------------------------------------------------------------------- */static int init_s503 (sdlahw_t* hw){	unsigned port = hw->port;	int tmp, i;	if (!detect_s503(port))		return -ENODEV;	/* Verify configuration options */	i = get_option_index(s508_dpmbase_options, virt_to_phys(hw->dpmbase));	if (i == 0)		return -EINVAL;	tmp = s502e_hmcr[i - 1];	switch (hw->dpmsize) {	case 0x2000:		tmp |= 0x01;		break;	case 0x10000L:		break;	default:		return -EINVAL;	}	/* Setup dual-port memory window */	_OUTB(port + 1, tmp);	hw->regs[1] = tmp;	/* Enable memory access */	_OUTB(port, 0x02);	hw->regs[0] = 0x02;	/* update mirror */	return 0;}/*============================================================================ * Initialize S507 adapter. */static int init_s507 (sdlahw_t* hw){	unsigned port = hw->port;	int tmp, i;	if (!detect_s507(port))		return -ENODEV;	/* Verify configuration options */	i = get_option_index(s507_dpmbase_options, virt_to_phys(hw->dpmbase));	if (i == 0)		return -EINVAL;	tmp = s507_hmcr[i - 1];	switch (hw->dpmsize) {	case 0x2000:		tmp |= 0x01;		break;	case 0x10000L:		break;	default:		return -EINVAL;	}	/* Enable adapter's logic */	_OUTB(port, 0x01);	hw->regs[0] = 0x01;	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */	if (!(_INB(port) & 0x20))		return -EIO;	/* Setup dual-port memory window */	_OUTB(port + 1, tmp);	hw->regs[1] = tmp;	/* Enable memory access */	tmp = hw->regs[0] | 0x04;	if (hw->irq) {		i = get_option_index(s508_irq_options, hw->irq);		if (i) tmp |= s507_irqmask[i - 1];	}	_OUTB(port, tmp);	hw->regs[0] = tmp;		/* update mirror */	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */	return (_INB(port) & 0x08) ? 0 : -EIO;}/*============================================================================ * Initialize S508 adapter. */static int init_s508 (sdlahw_t* hw){	unsigned port = hw->port;	int tmp, i;	if (!detect_s508(port))		return -ENODEV;	/* Verify configuration options */	i = get_option_index(s508_dpmbase_options, virt_to_phys(hw->dpmbase));	if (i == 0)		return -EINVAL;	/* Setup memory configuration */	tmp = s508_hmcr[i - 1];	_OUTB(port + 1, tmp);	hw->regs[1] = tmp;	/* Enable memory access */	_OUTB(port, 0x04);	hw->regs[0] = 0x04;		/* update mirror */	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */	return (_INB(port + 1) & 0x04) ? 0 : -EIO;}/*============================================================================ * Detect S502A adapter. *	Following tests are used to detect S502A adapter: *	1. All registers other than status (BASE) should read 0xFF *	2. After writing 00001000b to control register, status register should *	   read 01000000b. *	3. After writing 0 to control register, status register should still *	   read  01000000b. *	4. After writing 00000100b to control register, status register should *	   read 01000100b. *	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_s502a (int port){	int i, j;	if (!get_option_index(s502_port_options, port))		return 0;		for (j = 1; j < SDLA_MAXIORANGE; ++j) {		if (_INB(port + j) != 0xFF)			return 0;		for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */	}	_OUTB(port, 0x08);			/* halt CPU */	_OUTB(port, 0x08);	_OUTB(port, 0x08);	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */	if (_INB(port) != 0x40)		return 0;	_OUTB(port, 0x00);	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */	if (_INB(port) != 0x40)		return 0;	_OUTB(port, 0x04);	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */	if (_INB(port) != 0x44)		return 0;	/* Reset adapter */	_OUTB(port, 0x08);	_OUTB(port, 0x08);	_OUTB(port, 0x08);	_OUTB(port + 1, 0xFF);	return 1;}/*============================================================================ * Detect S502E adapter. *	Following tests are used to verify adapter presence: *	1. All registers other than status (BASE) should read 0xFF. *	2. After writing 0 to CPU control register (BASE+3), status register *	   (BASE) should read 11111000b. *	3. After writing 00000100b to port BASE (set bit 2), status register *	   (BASE) should read 11111100b. *	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_s502e (int port){	int i, j;	if (!get_option_index(s502_port_options, port))		return 0;	for (j = 1; j < SDLA_MAXIORANGE; ++j) {		if (_INB(port + j) != 0xFF)			return 0;		for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */	}	_OUTB(port + 3, 0);			/* CPU control reg. */	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */	if (_INB(port) != 0xF8)			/* read status */

⌨️ 快捷键说明

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