cronyx.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 1,061 行 · 第 1/2 页

C
1,061
字号
/* * Low-level subroutines for Cronyx-Sigma adapter. * * Copyright (C) 1994-95 Cronyx Ltd. * Author: Serge Vakulenko, <vak@cronyx.ru> * * This software is distributed with NO WARRANTIES, not even the implied * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * Authors grant any other persons or organisations permission to use * or modify this software as long as this message is kept with the software, * all derivative works or modified versions. * * Version 1.6, Wed May 31 16:03:20 MSD 1995 */#if defined (MSDOS) || defined (__MSDOS__)#   include <string.h>#   include <dos.h>#   define inb(port)    inportb(port)#   define inw(port)    inport(port)#   define outb(port,b) outportb(port,b)#   define outw(port,w)	outport(port,w)#   define vtophys(a)	(((unsigned long)(a)>>12 & 0xffff0) +\			((unsigned)(a) & 0xffff))#   include "cronyx.h"#   include "cxreg.h"#else#   include <sys/param.h>#   include <sys/systm.h>#   include <sys/socket.h>#   include <net/if.h>#   include <vm/vm.h>#   ifndef __FreeBSD__#      include <machine/inline.h>#   endif#   include <machine/cronyx.h>#   include <i386/isa/cxreg.h>#endif#define DMA_MASK	0xd4	/* DMA mask register */#define DMA_MASK_CLEAR	0x04	/* DMA clear mask */#define DMA_MODE	0xd6	/* DMA mode register */#define DMA_MODE_MASTER	0xc0	/* DMA master mode */#define BYTE *(unsigned char*)&static unsigned char irqmask [] = {	BCR0_IRQ_DIS,	BCR0_IRQ_DIS,	BCR0_IRQ_DIS,	BCR0_IRQ_3,	BCR0_IRQ_DIS,	BCR0_IRQ_5,	BCR0_IRQ_DIS,	BCR0_IRQ_7,	BCR0_IRQ_DIS,	BCR0_IRQ_DIS,	BCR0_IRQ_10,	BCR0_IRQ_11,	BCR0_IRQ_12,	BCR0_IRQ_DIS,	BCR0_IRQ_DIS,	BCR0_IRQ_15,};static unsigned char dmamask [] = {	BCR0_DMA_DIS,	BCR0_DMA_DIS,	BCR0_DMA_DIS,	BCR0_DMA_DIS,	BCR0_DMA_DIS,	BCR0_DMA_5,	BCR0_DMA_6,	BCR0_DMA_7,};long cx_rxbaud = CX_SPEED_DFLT;	/* receiver baud rate */long cx_txbaud = CX_SPEED_DFLT;	/* transmitter baud rate */int cx_univ_mode = M_ASYNC;	/* univ. chan. mode: async or sync */int cx_sync_mode = M_HDLC;	/* sync. chan. mode: HDLC, Bisync or X.21 */int cx_iftype = 0;		/* univ. chan. interface: upper/lower */static int cx_probe_chip (int base);static void cx_setup_chip (cx_chip_t *c);/* * Wait for CCR to clear. */void cx_cmd (int base, int cmd){	unsigned short port = CCR(base);	unsigned short count;	/* Wait 10 msec for the previous command to complete. */	for (count=0; inb(port) && count<20000; ++count)		continue;	/* Issue the command. */	outb (port, cmd);	/* Wait 10 msec for the command to complete. */	for (count=0; inb(port) && count<20000; ++count)		continue;}/* * Reset the chip. */static int cx_reset (unsigned short port){	int count;	/* Wait up to 10 msec for revision code to appear after reset. */	for (count=0; count<20000; ++count)		if (inb(GFRCR(port)) != 0)			break;	cx_cmd (port, CCR_RSTALL);	/* Firmware revision code should clear imediately. */	/* Wait up to 10 msec for revision code to appear again. */	for (count=0; count<20000; ++count)		if (inb(GFRCR(port)) != 0)			return (1);	/* Reset failed. */	return (0);}/* * Check if the CD2400 board is present at the given base port. */static int cx_probe_chained_board (int port, int *c0, int *c1){	int rev, i;	/* Read and check the board revision code. */	rev = inb (BSR(port));	*c0 = *c1 = 0;	switch (rev & BSR_VAR_MASK) {	case CRONYX_100:	*c0 = 1;	break;	case CRONYX_400:	*c1 = 1;	break;	case CRONYX_500:	*c0 = *c1 = 1;	break;	case CRONYX_410:	*c0 = 1;	break;	case CRONYX_810:	*c0 = *c1 = 1;	break;	case CRONYX_410s:	*c0 = 1;	break;	case CRONYX_810s:	*c0 = *c1 = 1;	break;	case CRONYX_440:	*c0 = 1;	break;	case CRONYX_840:	*c0 = *c1 = 1;	break;	case CRONYX_401:	*c0 = 1;	break;	case CRONYX_801:	*c0 = *c1 = 1;	break;	case CRONYX_401s:	*c0 = 1;	break;	case CRONYX_801s:	*c0 = *c1 = 1;	break;	case CRONYX_404:	*c0 = 1;	break;	case CRONYX_703:	*c0 = *c1 = 1;	break;	default:		return (0);	/* invalid variant code */	}	switch (rev & BSR_OSC_MASK) {	case BSR_OSC_20:	/* 20 MHz */	case BSR_OSC_18432:	/* 18.432 MHz */		break;	default:		return (0);	/* oscillator frequency does not match */	}	for (i=2; i<0x10; i+=2)		if ((inb (BSR(port)+i) & BSR_REV_MASK) != (rev & BSR_REV_MASK))			return (0);	/* status changed? */	return (1);}/* * Check if the CD2400 board is present at the given base port. */int cx_probe_board (int port){	int c0, c1, c2=0, c3=0, result;	if (! cx_probe_chained_board (port, &c0, &c1))		return (0);     /* no board detected */	if (! (inb (BSR(port)) & BSR_NOCHAIN)) { /* chained board attached */		if (! cx_probe_chained_board (port + 0x10, &c2, &c3))			return (0);     /* invalid chained board? */		if (! (inb (BSR(port+0x10)) & BSR_NOCHAIN))			return (0);     /* invalid chained board flag? */	}	/* Turn off the reset bit. */	outb (BCR0(port), BCR0_NORESET);	if (c2 || c3)		outb (BCR0(port + 0x10), BCR0_NORESET);	result = 1;	if (c0 && ! cx_probe_chip (CS0(port)))		result = 0;	/* no CD2400 chip here */	else if (c1 && ! cx_probe_chip (CS1(port)))		result = 0;	/* no second CD2400 chip */	else if (c2 && ! cx_probe_chip (CS0(port + 0x10)))		result = 0;	/* no CD2400 chip on the slave board */	else if (c3 && ! cx_probe_chip (CS1(port + 0x10)))		result = 0;	/* no second CD2400 chip on the slave board */	/* Reset the controller. */	outb (BCR0(port), 0);	if (c2 || c3)		outb (BCR0(port + 0x10), 0);	/* Yes, we really have valid CD2400 board. */	return (result);}/* * Check if the CD2400 chip is present at the given base port. */static int cx_probe_chip (int base){	int rev, newrev, count;	/* Wait up to 10 msec for revision code to appear after reset. */	for (count=0; inb(GFRCR(base))==0; ++count)		if (count >= 20000)			return (0); /* reset failed */	/* Read and check the global firmware revision code. */	rev = inb (GFRCR(base));	if (rev<REVCL_MIN || rev>REVCL_MAX)		return (0);	/* CD2400 revision does not match */	/* Reset the chip. */	if (! cx_reset (base))		return (0);	/* Read and check the new global firmware revision code. */	newrev = inb (GFRCR(base));	if (newrev != rev)		return (0);	/* revision changed */	/* Yes, we really have CD2400 chip here. */	return (1);}/* * Probe and initialize the board structure. */void cx_init (cx_board_t *b, int num, int port, int irq, int dma){	int rev, chain, rev2;	rev = inb (BSR(port));	chain = !(rev & BSR_NOCHAIN);	rev2 = chain ? inb (BSR(port+0x10)) : 0;	cx_init_board (b, num, port, irq, dma, chain,		(rev & BSR_VAR_MASK), (rev & BSR_OSC_MASK),		(rev2 & BSR_VAR_MASK), (rev2 & BSR_OSC_MASK));}/* * Initialize the board structure, given the type of the board. */void cx_init_board (cx_board_t *b, int num, int port, int irq, int dma,	int chain, int rev, int osc, int rev2, int osc2){	cx_chan_t *c;	int i, c0, c1;	/* Initialize board structure. */	b->port = port;	b->num = num;	b->irq = irq;	b->dma = dma;	b->if0type = b->if8type = cx_iftype;	/* Set channels 0 and 8 mode, set DMA and IRQ. */	b->bcr0 = b->bcr0b = BCR0_NORESET | dmamask[b->dma] | irqmask[b->irq];	/* Clear DTR[0..3] and DTR[8..12]. */	b->bcr1 = b->bcr1b = 0;	/* Initialize chip structures. */	for (i=0; i<NCHIP; ++i) {		b->chip[i].num = i;		b->chip[i].board = b;	}	b->chip[0].port = CS0(port);	b->chip[1].port = CS1(port);	b->chip[2].port = CS0(port+0x10);	b->chip[3].port = CS1(port+0x10);	/*------------------ Master board -------------------*/	/* Read and check the board revision code. */	c0 = c1 = 0;	b->name[0] = 0;	switch (rev) {	case CRONYX_100:  strcpy (b->name, "100");  c0 = 1;      break;	case CRONYX_400:  strcpy (b->name, "400");  c1 = 1;      break;	case CRONYX_500:  strcpy (b->name, "500");  c0 = c1 = 1; break;	case CRONYX_410:  strcpy (b->name, "410");  c0 = 1;      break;	case CRONYX_810:  strcpy (b->name, "810");  c0 = c1 = 1; break;	case CRONYX_410s: strcpy (b->name, "410s"); c0 = 1;      break;	case CRONYX_810s: strcpy (b->name, "810s"); c0 = c1 = 1; break;	case CRONYX_440:  strcpy (b->name, "440");  c0 = 1;      break;	case CRONYX_840:  strcpy (b->name, "840");  c0 = c1 = 1; break;	case CRONYX_401:  strcpy (b->name, "401");  c0 = 1;      break;	case CRONYX_801:  strcpy (b->name, "801");  c0 = c1 = 1; break;	case CRONYX_401s: strcpy (b->name, "401s"); c0 = 1;      break;	case CRONYX_801s: strcpy (b->name, "801s"); c0 = c1 = 1; break;	case CRONYX_404:  strcpy (b->name, "404");  c0 = 1;      break;	case CRONYX_703:  strcpy (b->name, "703");  c0 = c1 = 1; break;	}	switch (osc) {	default:	case BSR_OSC_20: /* 20 MHz */		b->chip[0].oscfreq = b->chip[1].oscfreq = 20000000L;		strcat (b->name, "a");		break;	case BSR_OSC_18432: /* 18.432 MHz */		b->chip[0].oscfreq = b->chip[1].oscfreq = 18432000L;		strcat (b->name, "b");		break;	}	if (! c0)		b->chip[0].port = 0;	if (! c1)		b->chip[1].port = 0;	/*------------------ Slave board -------------------*/	if (! chain) {		b->chip[2].oscfreq = b->chip[3].oscfreq = 0L;		b->chip[2].port = b->chip[3].port = 0;	} else {		/* Read and check the board revision code. */		c0 = c1 = 0;		strcat (b->name, "/");		switch (rev2) {		case CRONYX_100:  strcat(b->name,"100");  c0=1;    break;		case CRONYX_400:  strcat(b->name,"400");  c1=1;    break;		case CRONYX_500:  strcat(b->name,"500");  c0=c1=1; break;		case CRONYX_410:  strcat(b->name,"410");  c0=1;    break;		case CRONYX_810:  strcat(b->name,"810");  c0=c1=1; break;		case CRONYX_410s: strcat(b->name,"410s"); c0=1;    break;		case CRONYX_810s: strcat(b->name,"810s"); c0=c1=1; break;		case CRONYX_440:  strcat(b->name,"440");  c0=1;    break;		case CRONYX_840:  strcat(b->name,"840");  c0=c1=1; break;		case CRONYX_401:  strcat(b->name,"401");  c0=1;    break;		case CRONYX_801:  strcat(b->name,"801");  c0=c1=1; break;		case CRONYX_401s: strcat(b->name,"401s"); c0=1;    break;		case CRONYX_801s: strcat(b->name,"801s"); c0=c1=1; break;		case CRONYX_404:  strcat(b->name,"404");  c0=1;    break;		case CRONYX_703:  strcat(b->name,"703");  c0=c1=1; break;		}		switch (osc2) {		default:		case BSR_OSC_20: /* 20 MHz */			b->chip[2].oscfreq = b->chip[3].oscfreq = 20000000L;			strcat (b->name, "a");			break;		case BSR_OSC_18432: /* 18.432 MHz */			b->chip[2].oscfreq = b->chip[3].oscfreq = 18432000L;			strcat (b->name, "b");			break;		}		if (! c0)			b->chip[2].port = 0;		if (! c1)			b->chip[3].port = 0;	}	/* Initialize channel structures. */	for (i=0; i<NCHAN; ++i) {		cx_chan_t *c = b->chan + i;		c->num = i;		c->board = b;		c->chip = b->chip + i*NCHIP/NCHAN;		c->stat = b->stat + i;		c->type = T_NONE;	}	/*------------------ Master board -------------------*/	switch (rev) {	case CRONYX_400:		break;	case CRONYX_100:	case CRONYX_500:		b->chan[0].type = T_UNIV_RS232;		break;	case CRONYX_410:	case CRONYX_810:		b->chan[0].type = T_UNIV_V35;		for (i=1; i<4; ++i)			b->chan[i].type = T_UNIV_RS232;		break;	case CRONYX_410s:	case CRONYX_810s:		b->chan[0].type = T_UNIV_V35;		for (i=1; i<4; ++i)			b->chan[i].type = T_SYNC_RS232;		break;	case CRONYX_440:	case CRONYX_840:		b->chan[0].type = T_UNIV_V35;		for (i=1; i<4; ++i)			b->chan[i].type = T_SYNC_V35;		break;	case CRONYX_401:	case CRONYX_801:		b->chan[0].type = T_UNIV_RS449;		for (i=1; i<4; ++i)			b->chan[i].type = T_UNIV_RS232;		break;	case CRONYX_401s:	case CRONYX_801s:		b->chan[0].type = T_UNIV_RS449;		for (i=1; i<4; ++i)			b->chan[i].type = T_SYNC_RS232;		break;	case CRONYX_404:		b->chan[0].type = T_UNIV_RS449;		for (i=1; i<4; ++i)			b->chan[i].type = T_SYNC_RS449;		break;	case CRONYX_703:		b->chan[0].type = T_UNIV_RS449;		for (i=1; i<3; ++i)			b->chan[i].type = T_SYNC_RS449;		break;	}	/* If the second controller is present,	 * then we have 4..7 channels in async. mode */	if (b->chip[1].port)		for (i=4; i<8; ++i)			b->chan[i].type = T_UNIV_RS232;	/*------------------ Slave board -------------------*/	if (chain) {		switch (rev2) {		case CRONYX_400:			break;		case CRONYX_100:		case CRONYX_500:			b->chan[8].type = T_UNIV_RS232;			break;		case CRONYX_410:		case CRONYX_810:			b->chan[8].type = T_UNIV_V35;			for (i=9; i<12; ++i)				b->chan[i].type = T_UNIV_RS232;			break;		case CRONYX_410s:		case CRONYX_810s:			b->chan[8].type = T_UNIV_V35;			for (i=9; i<12; ++i)				b->chan[i].type = T_SYNC_RS232;			break;		case CRONYX_440:		case CRONYX_840:			b->chan[8].type = T_UNIV_V35;			for (i=9; i<12; ++i)				b->chan[i].type = T_SYNC_V35;			break;		case CRONYX_401:		case CRONYX_801:			b->chan[8].type = T_UNIV_RS449;			for (i=9; i<12; ++i)				b->chan[i].type = T_UNIV_RS232;			break;		case CRONYX_401s:		case CRONYX_801s:			b->chan[8].type = T_UNIV_RS449;			for (i=9; i<12; ++i)				b->chan[i].type = T_UNIV_RS232;			break;		case CRONYX_404:			b->chan[8].type = T_UNIV_RS449;			for (i=9; i<12; ++i)				b->chan[i].type = T_SYNC_RS449;			break;		case CRONYX_703:			b->chan[8].type = T_UNIV_RS449;			for (i=9; i<11; ++i)				b->chan[i].type = T_SYNC_RS449;			break;		}		/* If the second controller is present,		 * then we have 4..7 channels in async. mode */		if (b->chip[3].port)			for (i=12; i<16; ++i)				b->chan[i].type = T_UNIV_RS232;	}	b->nuniv = b->nsync = b->nasync = 0;	for (c=b->chan; c<b->chan+NCHAN; ++c)		switch (c->type) {		case T_ASYNC:      ++b->nasync; break;		case T_UNIV_RS232:		case T_UNIV_RS449:		case T_UNIV_V35:   ++b->nuniv;  break;		case T_SYNC_RS232:		case T_SYNC_V35:		case T_SYNC_RS449: ++b->nsync;  break;		}	cx_reinit_board (b);}/* * Reinitialize all channels, using new options and baud rate. */void cx_reinit_board (cx_board_t *b){	cx_chan_t *c;	b->if0type = b->if8type = cx_iftype;	for (c=b->chan; c<b->chan+NCHAN; ++c) {		switch (c->type) {		default:		case T_NONE:			continue;		case T_UNIV_RS232:		case T_UNIV_RS449:		case T_UNIV_V35:			c->mode = (cx_univ_mode == M_ASYNC) ?				M_ASYNC : cx_sync_mode;			break;		case T_SYNC_RS232:		case T_SYNC_V35:		case T_SYNC_RS449:			c->mode = cx_sync_mode;			break;		case T_ASYNC:			c->mode = M_ASYNC;			break;		}		c->rxbaud = cx_rxbaud;		c->txbaud = cx_txbaud;

⌨️ 快捷键说明

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