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

📄 sdladrv.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
 * 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 */		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:

⌨️ 快捷键说明

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