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

📄 sdladrv.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
	case SDLA_S503:	case SDLA_S507:	case SDLA_S508:		bootp = hw->dpmbase;		break;	default:		return -EINVAL;	}	err = sdla_mapmem(hw, 0);	if (err) return err;	*bootp = 0xC3;	 /* Z80: 'jp' opcode */	bootp++;	*((unsigned short*)(bootp)) = addr;	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;	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 */		return 0	;	_OUTB(port, 0x04);			/* set bit 2 */	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */	if (_INB(port) != 0xFC)			/* verify */		return 0	;	/* Reset adapter */	_OUTB(port, 0);	return 1;}/*============================================================================ * Detect s503 adapter. *	Following tests are used to verify adapter presence: *	1. All registers other than status (BASE) should read 0xFF. *	2. After writing 0 to control register (BASE), status register (BASE) *	   should read 11110000b. *	3. After writing 00000100b (set bit 2) to control register (BASE), *	   status register should read 11110010b. *	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_s503 (int port){	int i, j;	if (!get_option_index(s503_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, 0);				/* reset control reg.*/	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */	if (_INB(port) != 0xF0)			/* read status */		return 0	;	_OUTB(port, 0x04);			/* set bit 2 */	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */	if (_INB(port) != 0xF2)			/* verify */		return 0	;	/* Reset adapter */	_OUTB(port, 0);	return 1;}/*============================================================================ * Detect s507 adapter. *	Following tests are used to detect s507 adapter: *	1. All ports should read the same value. *	2. After writing 0x00 to control register, status register should read *	   ?011000?b. *	3. After writing 0x01 to control register, status register should read *	   ?011001?b. *	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_s507 (int port){	int tmp, i, j;	if (!get_option_index(s508_port_options, port))		return 0	;	tmp = _INB(port);	for (j = 1; j < S507_IORANGE; ++j)	{		if (_INB(port + j) != tmp)			return 0		;		for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */	}	_OUTB(port, 0x00);	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */	if ((_INB(port) & 0x7E) != 0x30)		return 0	;	_OUTB(port, 0x01);	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */	if ((_INB(port) & 0x7E) != 0x32)		return 0	;	/* Reset adapter */	_OUTB(port, 0x00);	return 1;}/*============================================================================ * Detect s508 adapter. *	Following tests are used to detect s508 adapter: *	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;}/******* 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 && (*p == 0xFF); --len, ++p)	{		*p = 0;			/* attempt to write 0 */		if (*p != 0xFF)		/* still has to read 0xFF */		{			*p = 0xFF;	/* 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)		*w_ptr = 0xAA55	;	for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)		if (*w_ptr != 0xAA55)		{			len_w = i;			break;		}	;	for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)		*w_ptr = 0x55AA	;	for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)		if (*w_ptr != 0x55AA)		{			len_w = i;			break;		}	;	for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr) *w_ptr = 0;	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;}/****** End *****************************************************************/

⌨️ 快捷键说明

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