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

📄 hs.c

📁 嵌入式TCP/IP协议栈。 C 源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Interface driver for the DRSI PCPA or the Eagle 8530 boards for the IBM PC
 * connected to a WA4DSY 56kbps modem. Uses polling-loop transfers with
 * interrupts disabled for maximum speed.
 *
 * This driver is a bit of a kludge. A DMA-driven card and driver (e.g.,
 * the PI) is much better, but this is better than nothing if all you have
 * is a "dumb" 8530 card.
 *
 */
#include <stdio.h>
#include <dos.h>
#include "global.h"
#include "mbuf.h"
#include "iface.h"
#include "pktdrvr.h"
#include "netuser.h"
#include "hs.h"
#include "z8530.h"
#include "ax25.h"
#include "trace.h"
#include "nospc.h"
#include "proc.h"
#include "devparam.h"

static void flushrx(uint16 data);
static void hdlcparam(struct hdlc *hp);
static void hexint(struct hdlc *hp);
static void hrxint(struct hdlc *hp);
static int hs_stop(struct iface *iface);
static int hs_raw(struct iface *iface,struct mbuf **bpp);
static int32 hs_ctl(struct iface *,int cmd,int set,int32 val);
static void hstxoff(struct hdlc *hp);
static void hstxon(struct hdlc *hp);
static void htxint(struct hdlc *hp);
static void init_delay(void);
static void msdelay(void);

static struct hs Hs[NHS];
static INTERRUPT (*Hshandle[])() = { hs0vec };
static struct hdlc Hdlc[2*NHS];
static uint16 Nhs;

/* Master interrupt handler for the PC-100 card. All interrupts come
 * here first, then are switched out to the appropriate routine.
 */
INTERRUPT (far *(hsint)(dev))()
int dev;
{
	register char iv;
	uint16 hsbase;
	struct hs *hsp;
	register struct hdlc *hp;
	
	hsp = &Hs[dev];
	hsp->ints++;
	hsbase = hsp->addr;

#ifdef	foo
	outportb(hsbase+4,0x8+0x10);	/* HIT EAGLE INTACK */
	(void)inportb(hsbase+CHANA+CTL,R0);
	outportb(hsbase+4,0x8);		/***/
#endif

	/* Read interrupt status from channel A */
	while((iv = read_scc(hsbase+CHANA+CTL,R3)) != 0){
		if(iv & CHARxIP){
			/* Channel A Rcv Interrupt Pending */
			hp = &Hdlc[2*dev];
			hrxint(hp);
		} else if(iv & CHATxIP){
			/* Channel A Transmit Int Pending */
			hp = &Hdlc[2*dev];
			htxint(hp);
		} else if(iv & CHAEXT){
			/* Channel A External Status Int */
			hp = &Hdlc[2*dev];
			hexint(hp);
		} else if(iv & CHBRxIP){
			/* Channel B Rcv Interrupt Pending */
			hp = &Hdlc[(2*dev)+1];
			hrxint(hp);
		} else if(iv & CHBTxIP){
			/* Channel B Transmit Int Pending */
			hp = &Hdlc[(2*dev)+1];
			htxint(hp);
		} else if(iv & CHBEXT){
			/* Channel B External Status Int */
			hp = &Hdlc[(2*dev)+1];
			hexint(hp);
		}
		/* Reset interrupt pending state */
		write_scc(hp->ctl,R0,RES_H_IUS);
		outportb(hsbase+CHANA+CTL,0);	/* Restore pointer to 0 */
		outportb(hsbase+CHANB+CTL,0);	/* Restore pointer to 0 */
	}
	outportb(hsbase+CHANA+CTL,0);	/* Restore pointer to 0 */
	outportb(hsbase+CHANB+CTL,0);	/* Restore pointer to 0 */
	return hsp->chain ? hsp->save.vec : NULL;
}
/* HDLC SIO External/Status interrupts
 * The only one that can happen in this driver is a DCD change
 */
static void
hexint(hp)
register struct hdlc *hp;
{
	struct mbuf *rcvbuf;
	char *cp;
	int cnt,data;
	register int ctl;

	ctl = hp->ctl;
	data = hp->data;
	hp->exints++;

	/* Allocate a receive buffer */
	if((rcvbuf = alloc_mbuf(hp->bufsiz+sizeof(struct iface *))) == NULL){
		/* Alloc failed; refuse to proceed */
		hp->nomem++;
		write_scc(ctl,R3,ENT_HM|RxENABLE|RxCRC_ENAB|Rx8);
		write_scc(ctl,R0,RES_EXT_INT);
		return;
	}
	/* Allow space for descriptor on front */
	rcvbuf->data += sizeof(struct iface *);
	cnt = 0;

	/* Disable DCDIE bit so we can track changes in DCD */
	write_scc(ctl,R15,0);

	write_scc(ctl,R3,ENT_HM|RxENABLE|RxCRC_ENAB|Rx8);
	flushrx(data);
	while((cnt = rx8530(ctl,data,cp,hp->bufsiz)) != -1){
		if(cnt > 4){
			/* Good frame */
			hp->good++;
			/* Toss crc */
			rcvbuf->cnt = cnt - 1;
			net_route(hp->iface,&rcvbuf);
			/* Replenish buffer */
			rcvbuf = alloc_mbuf(hp->bufsiz + sizeof(struct iface *));
		}
		/* Start new buffer */
		if(rcvbuf == NULL)
			break;	/* alloc failed */
		rcvbuf->data +=  sizeof(struct iface *);
	}	
	write_scc(ctl,R0,RES_EXT_INT);
	write_scc(ctl,R15,DCDIE);	/* Re-enable DCD */
	write_scc(ctl,R3,ENT_HM|RxENABLE|RxCRC_ENAB|Rx8);

	/* Get rid of fragmentary buffer */
	free_p(&rcvbuf);
}
static void
flushrx(data)
register uint16 data;
{
	register int i = 5;
	while(i-- != 0)
		(void)inportb(data);
}
/* HDLC receiver interrupt handler.
 * Not used in this driver
 */
static void
hrxint(hp)
register struct hdlc *hp;
{
}
/* HDLC transmit interrupt service routine
 * Not used in this driver
 */
static void
htxint(hp)
register struct hdlc *hp;
{
}

/* (re)Initialize HDLC controller parameters */
static void
hdlcparam(hp)
register struct hdlc *hp;
{
	register uint16 ctl;
	int i_state;

	/* Initialize 8530 channel for SDLC operation */
	ctl = hp->ctl;
	i_state = dirps();

#ifdef	foo
	switch(ctl & 2){
	case CHANA:
		write_scc(ctl,R9,CHRA);	/* Reset channel A */
		break;
	case CHANB:
		write_scc(ctl,R9,CHRB);	/* Reset channel B */
		break;
	}
	ppause(1L);	/* Allow plenty of time for resetting */
#endif

	/* Deselect interrupts for now */
	write_scc(ctl,R1,0);
	write_scc(ctl,R15,0);

	/* X1 clock, SDLC mode, Sync modes enable, parity disable */
	write_scc(ctl,R4,X1CLK | SDLC | SYNC_ENAB);

	/* CRC preset 1, NRZ encoding, no active on poll, flag idle,
	 * flag on underrun, no loop mode, 8 bit sync
	 */
	write_scc(ctl,R10,CRCPS|NRZ);

	/* 8530 gets both tx and rx clock from modem.
	 * By default, TRxC = transmit clock, RTxC = receive clock
	 * (swapped 11 Feb 1990 to use new DRSI wiring) UNLESS
	 * the 'r' parameter is specified
	 */
	if(!hp->clkrev)
		write_scc(ctl,R11,RCRTxCP | TCTRxCP);
	else
		write_scc(ctl,R11,RCTRxCP | TCRTxCP);

	/* Note: baud rate generator not used */

	/* Null out SDLC start address */
	write_scc(ctl,R6,0);

	/* SDLC flag */
	write_scc(ctl,R7,FLAG);

	/* DTR On, 8 bit TX chars, no break, TX enable, SDLC CRC,
	 * RTS off, TxCRC enable
	 */
	write_scc(ctl,R5,DTR|Tx8|TxENAB|TxCRC_ENAB);

	/* 8 bit RX chars, auto enables off, no hunt mode, RxCRC enable,
	 * no address search, no inhibit sync chars, disable RX. Rx is
	 * started only by an actual DCD interrupt
	 */
	write_scc(ctl,R3,RxENABLE|RxCRC_ENAB|Rx8);

	/* Dummy interrupt vector
	 * (This probably isn't necessary)
	 */
	write_scc(ctl,R2,0);

	/* Enable only the external interrupts (modem interrupts) since
	 * polling is used for all actual tx/rx operations
	 */
	write_scc(ctl,R1,EXT_INT_ENAB);

	/* Enable only DCD interrupts */
	write_scc(ctl,R15,DCDIE);

	/* No reset, status low, master int enable, enable lower chain,
	 * no vector
	 */
	write_scc(ctl,R9,MIE|NV);

	restore(i_state);
}
/* Attach a high speed iterface to the system
 * argv[0]: hardware type, must be "hs"
 * argv[1]: I/O address, e.g., "0x380"
 * argv[2]: vector, e.g., "2"
 * argv[3]: mode, must be "ax25"
 * argv[4]: interface base label, e.g., "drsi0". Driver appends "a" and "b".
 * argv[5]: receiver packet buffer size in bytes
 * argv[6]: maximum transmission unit, bytes
 * argv[7]: keyup delay, milliseconds
 * argv[8]: persistence value, 0-255
 * argv[9]: "r" to reverse sense of clock leads (optional)
 */
int
hs_attach(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	register struct iface *if_hsa,*if_hsb;
	struct hdlc *hp;
	int dev;
	char *cp;

	if(Nhs >= NHS){
		printf("Too many hs controllers\n");
		return -1;
	}
	if(if_lookup(argv[4]) != NULL){
		printf("Interface %s already exists\n",argv[4]);
		return -1;
	}
	if(setencap(NULL,argv[3]) == -1){
		printf("Unknown encapsulation %s\n",argv[3]);
		return -1;
	}
	if(Mycall[0] == '\0'){
		printf("set mycall first\n");
		return -1;
	}		
	dev = Nhs++;

	/* Initialize hardware-level control structure */
	Hs[dev].addr = htoi(argv[1]);
	Hs[dev].vec = atoi(argv[2]);
	if(strchr(argv[2],'c') != NULL)
		Hs[dev].chain = 1;
	else
		Hs[dev].chain = 0;

	/* Save original interrupt vector */
	Hs[dev].save.vec = getirq(Hs[dev].vec);
	/* Set new interrupt vector */
	if(setirq(Hs[dev].vec,Hshandle[dev]) == -1){
		printf("IRQ %u out of range\n",Hs[dev].vec);
		Nhs--;
		return -1;
	}
	/* Create interface structures and fill in details */
	if_hsa = (struct iface *)callocw(1,sizeof(struct iface));
	if_hsb = (struct iface *)callocw(1,sizeof(struct iface));

	if_hsa->addr = if_hsb->addr = Ip_addr;
	if_hsa->name = mallocw(strlen(argv[4])+2);
	strcpy(if_hsa->name,argv[4]);
	strcat(if_hsa->name,"a");
	if_hsb->name = mallocw(strlen(argv[4])+2);
	strcpy(if_hsb->name,argv[4]);
	strcat(if_hsb->name,"b");
	if_hsb->mtu = if_hsa->mtu = atoi(argv[6]);
	if_hsa->dev = 2*dev;
	if_hsb->dev = 2*dev + 1;
	if_hsb->stop = if_hsa->stop = hs_stop;
	if_hsb->raw = if_hsa->raw = hs_raw;
	if_hsa->ioctl = if_hsb->ioctl = hs_ctl;

	setencap(if_hsa,argv[3]);
	setencap(if_hsb,argv[3]);
	if(if_hsb->hwaddr == NULL)
		if_hsb->hwaddr = mallocw(AXALEN);
	memcpy(if_hsb->hwaddr,Mycall,AXALEN);
	if(if_hsa->hwaddr == NULL)
		if_hsa->hwaddr = mallocw(AXALEN);
	memcpy(if_hsa->hwaddr,Mycall,AXALEN);
	if_hsa->next = if_hsb;
	if_hsb->next = Ifaces;
	Ifaces = if_hsa;

	write_scc(Hs[dev].addr+CHANA+CTL,R9,FHWRES);
	hp = &Hdlc[2*dev+1];
	hp->ctl = Hs[dev].addr + CHANB + CTL;
	hp->data = Hs[dev].addr + CHANB + DATA;
	hp->bufsiz = atoi(argv[5]);
	if(argc > 7)

⌨️ 快捷键说明

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