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

📄 dgb.c

📁 freebsd v4.4内核源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/*- *  dgb.c $FreeBSD: src/sys/gnu/i386/isa/dgb.c,v 1.20.2.2 1999/09/05 08:10:03 peter Exp $ * *  Digiboard driver. * *  Stage 1. "Better than nothing". *  Stage 2. "Gee, it works!". * *  Based on sio driver by Bruce Evans and on Linux driver by Troy  *  De Jongh <troyd@digibd.com> or <troyd@skypoint.com>  *  which is under GNU General Public License version 2 so this driver  *  is forced to be under GPL 2 too. * *  Written by Serge Babkin, *      Joint Stock Commercial Bank "Chelindbank" *      (Chelyabinsk, Russia) *      babkin@hq.icb.chel.su * *  Assorted hacks to make it more functional and working under 3.0-current. *  Fixed broken routines to prevent processes hanging on closed (thanks *  to Bruce for his patience and assistance). Thanks also to Maxim Bolotin *  <max@run.net> for his patches which did most of the work to get this *  running under 2.2/3.0-current. *  Implemented ioctls: TIOCMSDTRWAIT, TIOCMGDTRWAIT, TIOCTIMESTAMP & *  TIOCDCDTIMESTAMP. *  Sysctl debug flag is now a bitflag, to filter noise during debugging. *	David L. Nugent <davidn@blaze.net.au> */#include "dgb.h"#if NDGB > 0 /* Helg: i.e.25 times per sec board will be polled */#define POLLSPERSEC 25/* How many charactes can we write to input tty rawq */#define DGB_IBUFSIZE (TTYHOG-100)/* the overall number of ports controlled by this driver */#ifndef NDGBPORTS#	define NDGBPORTS (NDGB*16)#endif#include <sys/param.h>#include <sys/systm.h>#include <sys/reboot.h>#include <sys/ioctl.h>#include <sys/tty.h>#include <sys/proc.h>#include <sys/conf.h>#include <sys/dkstat.h>#include <sys/file.h>#include <sys/uio.h>#include <sys/kernel.h>#include <sys/sysctl.h>#include <sys/malloc.h>#include <sys/syslog.h>#ifdef DEVFS#include <sys/devfsext.h>#endif /*DEVFS*/#include <machine/clock.h>#include <vm/vm.h>#include <vm/vm_param.h>#include <vm/pmap.h>#include <i386/isa/isa_device.h>#include <gnu/i386/isa/dgbios.h>#include <gnu/i386/isa/dgfep.h>#define DEBUG#include <gnu/i386/isa/dgreg.h>/* This avoids warnings: we're an isa device only * so it does not matter... */#undef outb#define outb outbv#define	CALLOUT_MASK		0x80#define	CONTROL_MASK		0x60#define	CONTROL_INIT_STATE	0x20#define	CONTROL_LOCK_STATE	0x40#define UNIT_MASK			0x30000#define PORT_MASK			0x1F#define	DEV_TO_UNIT(dev)	(MINOR_TO_UNIT(minor(dev)))#define	MINOR_MAGIC_MASK	(CALLOUT_MASK | CONTROL_MASK)#define	MINOR_TO_UNIT(mynor)	(((mynor) & UNIT_MASK)>>16)#define MINOR_TO_PORT(mynor)	((mynor) & PORT_MASK)/* types.  XXX - should be elsewhere */typedef u_char	bool_t;		/* boolean *//* digiboard port structure */struct dgb_p {	bool_t	status;	u_char unit;           /* board unit number */	u_char pnum;           /* port number */	u_char omodem;         /* FEP output modem status     */	u_char imodem;         /* FEP input modem status      */	u_char modemfake;      /* Modem values to be forced   */	u_char modem;          /* Force values                */	u_char hflow;	u_char dsr;	u_char dcd;	u_char stopc;	u_char startc;	u_char stopca;	u_char startca;	u_char fepstopc;	u_char fepstartc;	u_char fepstopca;	u_char fepstartca;	u_char txwin;	u_char rxwin;	ushort fepiflag;	ushort fepcflag;	ushort fepoflag;	ushort txbufhead;	ushort txbufsize;	ushort rxbufhead;	ushort rxbufsize;	int close_delay;	int count;	int blocked_open;	int event;	int asyncflags;	u_long statusflags;	u_char *txptr;	u_char *rxptr;	volatile struct board_chan *brdchan;	struct tty *tty;	bool_t  active_out;	/* nonzero if the callout device is open */	u_int	wopeners;	/* # processes waiting for DCD in open() */	/* Initial state. */	struct termios	it_in;	/* should be in struct tty */	struct termios	it_out;	/* Lock state. */	struct termios	lt_in;	/* should be in struct tty */	struct termios	lt_out;	bool_t	do_timestamp;	bool_t	do_dcd_timestamp;	struct timeval	timestamp;	struct timeval	dcd_timestamp;	/* flags of state, are used in sleep() too */	u_char closing;	/* port is being closed now */	u_char draining; /* port is being drained now */	u_char used;	/* port is being used now */	u_char mustdrain; /* data must be waited to drain in dgbparam() */#ifdef	DEVFS	struct	{		void	*tty;		void	*init;		void	*lock;		void	*cua;	} devfs_token;#endif};/* Digiboard per-board structure */struct dgb_softc {	/* struct board_info */	u_char status;	/* status: DISABLED/ENABLED */	u_char unit;	/* unit number */	u_char type;	/* type of card: PCXE, PCXI, PCXEVE */	u_char altpin;	/* do we need alternate pin setting ? */	ushort numports;	/* number of ports on card */	ushort port;	/* I/O port */	u_char *vmem; /* virtual memory address */	long pmem; /* physical memory address */	int mem_seg;  /* internal memory segment */	struct dgb_p *ports;	/* pointer to array of port descriptors */	struct tty *ttys;	/* pointer to array of TTY structures */	volatile struct global_data *mailbox;	};	static struct dgb_softc dgb_softc[NDGB];static struct dgb_p dgb_ports[NDGBPORTS];static struct tty dgb_tty[NDGBPORTS];/* * The public functions in the com module ought to be declared in a com-driver * system header. *//* Interrupt handling entry points. */static void	dgbpoll		__P((void *unit_c));/*static void	dgbintr		__P((int unit));*//* Device switch entry points. */#define	dgbreset	noreset#define	dgbmmap		nommap#define	dgbstrategy	nostrategystatic	int	dgbattach	__P((struct isa_device *dev));static	int	dgbprobe	__P((struct isa_device *dev));static void fepcmd(struct dgb_p *port, unsigned cmd, unsigned op1, unsigned op2,	unsigned ncmds, unsigned bytecmd);static	void	dgbstart	__P((struct tty *tp));static	int	dgbparam	__P((struct tty *tp, struct termios *t));static	void	dgbhardclose	__P((struct dgb_p *port));static	void	dgb_drain_or_flush	__P((struct dgb_p *port));static	int	dgbdrain	__P((struct dgb_p *port));static	void	dgb_pause	__P((void *chan));static	void	wakeflush	__P((void *p));static	void	disc_optim	__P((struct tty	*tp, struct termios *t));struct isa_driver	dgbdriver = {	dgbprobe, dgbattach, "dgb",0};static	d_open_t	dgbopen;static	d_close_t	dgbclose;static	d_read_t	dgbread;static	d_write_t	dgbwrite;static	d_ioctl_t	dgbioctl;static	d_stop_t	dgbstop;static	d_devtotty_t	dgbdevtotty;#define CDEV_MAJOR 58static struct cdevsw dgb_cdevsw = 	{ dgbopen,	dgbclose,	dgbread,	dgbwrite,	/*58*/	  dgbioctl,	dgbstop,	noreset,	dgbdevtotty, /* dgb */	  ttselect,	nommap,		NULL,	"dgb",	NULL,	-1 };static	speed_t	dgbdefaultrate = TTYDEF_SPEED;static	struct speedtab dgbspeedtab[] = {	0,	FEP_B0, /* old (sysV-like) Bx codes */	50,	FEP_B50,	75,	FEP_B75,	110,	FEP_B110,	134,	FEP_B134,	150,	FEP_B150,	200,	FEP_B200,	300,	FEP_B300,	600,	FEP_B600,	1200,	FEP_B1200,	1800,	FEP_B1800,	2400,	FEP_B2400,	4800,	FEP_B4800,	9600,	FEP_B9600,	19200,	FEP_B19200,	38400,	FEP_B38400,	57600,	(FEP_FASTBAUD|FEP_B50),	/* B50 & fast baud table */	115200, (FEP_FASTBAUD|FEP_B110), /* B100 & fast baud table */	-1,	-1};static struct dbgflagtbl{  tcflag_t in_mask;  tcflag_t in_val;  tcflag_t out_val;} dgb_cflags[] ={  { PARODD,   PARODD,	  FEP_PARODD  },  { PARENB,   PARENB,	  FEP_PARENB  },  { CSTOPB,   CSTOPB,	  FEP_CSTOPB  },  { CSIZE,    CS5,	  FEP_CS6     },  { CSIZE,    CS6,	  FEP_CS6     },  { CSIZE,    CS7,	  FEP_CS7     },  { CSIZE,    CS8,	  FEP_CS8     },  { CLOCAL,   CLOCAL,	  FEP_CLOCAL  },  { (tcflag_t)-1 }}, dgb_iflags[] ={  { IGNBRK,   IGNBRK,     FEP_IGNBRK  },  { BRKINT,   BRKINT,	  FEP_BRKINT  },  { IGNPAR,   IGNPAR,	  FEP_IGNPAR  },  { PARMRK,   PARMRK,	  FEP_PARMRK  },  { INPCK,    INPCK,	  FEP_INPCK   },  { ISTRIP,   ISTRIP,	  FEP_ISTRIP  },  { IXON,     IXON,	  FEP_IXON    },  { IXOFF,    IXOFF,	  FEP_IXOFF   },  { IXANY,    IXANY,	  FEP_IXANY   },  { (tcflag_t)-1 }}, dgb_flow[] ={  { CRTSCTS,  CRTSCTS,	  CTS|RTS     },  { CRTSCTS,  CCTS_OFLOW, CTS	      },  { CRTSCTS,  CRTS_IFLOW, RTS	      },  { (tcflag_t)-1 }};/* xlat bsd termios flags to dgb sys-v style */static tcflag_tdgbflags(struct dbgflagtbl *tbl, tcflag_t input){  tcflag_t output = 0;  int i;  for (i=0; tbl[i].in_mask != (tcflag_t)-1; i++)  {    if ((input & tbl[i].in_mask) == tbl[i].in_val)      output |= tbl[i].out_val;  }  return output;}static int dgbdebug=0;SYSCTL_INT(_debug, OID_AUTO, dgb_debug, CTLFLAG_RW,	&dgbdebug, 0, "");static int setwin __P((struct dgb_softc *sc, unsigned addr));static int setinitwin __P((struct dgb_softc *sc, unsigned addr));static void hidewin __P((struct dgb_softc *sc));static void towin __P((struct dgb_softc *sc, int win));/*Helg: to allow recursive dgb...() calls */typedef struct  {                 /* If we were called and don't want to disturb we need: */	short port,       /* write to this port */	      data;       /* this data on exit */	                  /* or DATA_WINOFF  to close memory window on entry */  } BoardMemWinState; /* so several channels and even boards can coexist */#define DATA_WINOFF 0static BoardMemWinState bmws;/* return current memory window state and close window */static BoardMemWinStatebmws_get(void){	BoardMemWinState bmwsRet=bmws;	if(bmws.data!=DATA_WINOFF)		outb(bmws.port, bmws.data=DATA_WINOFF);	return bmwsRet;}/* restore memory window state */static voidbmws_set(BoardMemWinState ws){	if(ws.data != bmws.data || ws.port!=bmws.port ) {		if(bmws.data!=DATA_WINOFF)			outb(bmws.port,DATA_WINOFF);		if(ws.data!=DATA_WINOFF)			outb(ws.port, ws.data);		bmws=ws;	}}static inline int setwin(sc,addr)	struct dgb_softc *sc;	unsigned int addr;{	if(sc->type==PCXEVE) {		outb(bmws.port=sc->port+1, bmws.data=FEPWIN|(addr>>13));		DPRINT3(DB_WIN,"dgb%d: switched to window 0x%x\n",sc->unit,addr>>13);		return (addr & 0x1FFF);	} else {		outb(bmws.port=sc->port,bmws.data=FEPMEM);		return addr;	}}static inline int setinitwin(sc,addr)	struct dgb_softc *sc;	unsigned int addr;{	if(sc->type==PCXEVE) {		outb(bmws.port=sc->port+1, bmws.data=FEPWIN|(addr>>13));		DPRINT3(DB_WIN,"dgb%d: switched to window 0x%x\n",sc->unit,addr>>13);		return (addr & 0x1FFF);	} else {		outb(bmws.port=sc->port,bmws.data=inb(sc->port)|FEPMEM);		return addr;	}}static inline voidhidewin(sc)	struct dgb_softc *sc;{	bmws.data=0;	if(sc->type==PCXEVE)		outb(bmws.port=sc->port+1, bmws.data);	else		outb(bmws.port=sc->port, bmws.data);}static inline voidtowin(sc,win)	struct dgb_softc *sc;	int win;{	if(sc->type==PCXEVE) {		outb(bmws.port=sc->port+1, bmws.data=win);	} else {		outb(bmws.port=sc->port,bmws.data=FEPMEM);	}}static intdgbprobe(dev)	struct isa_device	*dev;{	struct dgb_softc *sc= &dgb_softc[dev->id_unit];	int i, v, t;	u_long win_size;  /* size of vizible memory window */	u_char *mem;	int addr;	int unit=dev->id_unit;	sc->unit=dev->id_unit;	sc->port=dev->id_iobase;	if(dev->id_flags & DGBFLAG_ALTPIN)		sc->altpin=1;	else		sc->altpin=0;	/* left 24 bits only (ISA address) */	sc->pmem=((long)dev->id_maddr & 0xFFFFFF); 		DPRINT4(DB_INFO,"dgb%d: port 0x%x mem 0x%x\n",unit,sc->port,sc->pmem);	outb(sc->port, FEPRST);	sc->status=DISABLED;	for(i=0; i< 1000; i++) {		DELAY(1);		if( (inb(sc->port) & FEPMASK) == FEPRST ) {			sc->status=ENABLED;			DPRINT3(DB_EXCEPT,"dgb%d: got reset after %d us\n",unit,i);			break;		}	}	if(sc->status!=ENABLED) {		DPRINT2(DB_EXCEPT,"dgb%d: failed to respond\n",dev->id_unit);		return 0;	}	/* check type of card and get internal memory characteristics */	v=inb(sc->port);	if( v & 0x1 ) {		switch( v&0x30 ) {		case 0:			sc->mem_seg=0xF000;			win_size=0x10000;			printf("dgb%d: PC/Xi 64K\n",dev->id_unit);			break;		case 0x10:			sc->mem_seg=0xE000;			win_size=0x20000;			printf("dgb%d: PC/Xi 128K\n",dev->id_unit);			break;		case 0x20:			sc->mem_seg=0xC000;			win_size=0x40000;			printf("dgb%d: PC/Xi 256K\n",dev->id_unit);			break;		default: /* case 0x30: */			sc->mem_seg=0x8000;			win_size=0x80000;			printf("dgb%d: PC/Xi 512K\n",dev->id_unit);			break;		}		sc->type=PCXI;	} else {		outb(sc->port, 1);		v=inb(sc->port);		if( v & 0x1 ) {			printf("dgb%d: PC/Xm isn't supported\n",dev->id_unit);			sc->status=DISABLED;			return 0;			}		sc->mem_seg=0xF000;		if(dev->id_flags==DGBFLAG_NOWIN || ( v&0xC0 )==0) {			win_size=0x10000;			printf("dgb%d: PC/Xe 64K\n",dev->id_unit);			sc->type=PCXE;		} else {			win_size=0x2000;			printf("dgb%d: PC/Xe 64/8K (windowed)\n",dev->id_unit);			sc->type=PCXEVE;			if((u_long)sc->pmem & ~0xFFE000) {				printf("dgb%d: warning: address 0x%x truncated to 0x%x\n",					dev->id_unit, sc->pmem,					(long)sc->pmem & 0xFFE000);				dev->id_maddr= (u_char *)( (long)sc->pmem & 0xFFE000 );			}		}	}	/* save size of vizible memory segment */	dev->id_msize=win_size;	/* map memory */	dev->id_maddr=sc->vmem=pmap_mapdev(sc->pmem,dev->id_msize);	outb(sc->port, FEPCLR); /* drop RESET */	hidewin(sc); /* Helg: to set initial bmws state */	return 4; /* we need I/O space of 4 ports */}static intdgbattach(dev)	struct isa_device	*dev;{	int unit=dev->id_unit;	struct dgb_softc *sc= &dgb_softc[dev->id_unit];	int i, t;	u_char *mem;	u_char *ptr;	int addr;	struct dgb_p *port;	volatile struct board_chan *bc;	struct global_data *gd;	int shrinkmem;	int nfails;	ushort *pstat;	int lowwater;	static int nports=0;	if(sc->status!=ENABLED) {		DPRINT2(DB_EXCEPT,"dbg%d: try to attach a disabled card\n",unit);		return 0;		}	mem=sc->vmem;	DPRINT3(DB_INFO,"dgb%d: internal memory segment 0x%x\n",unit,sc->mem_seg);	outb(sc->port, FEPRST); DELAY(1);	for(i=0; (inb(sc->port) & FEPMASK) != FEPRST ; i++) {		if(i>10000) {			printf("dgb%d: 1st reset failed\n",dev->id_unit);			sc->status=DISABLED;			hidewin(sc);			return 0;		}		DELAY(1);	}	DPRINT3(DB_INFO,"dgb%d: got reset after %d us\n",unit,i);	/* for PCXEVE set up interrupt and base address */	if(sc->type==PCXEVE) {		t=(((u_long)sc->pmem>>8) & 0xFFE0) | 0x10 /* enable windowing */;		/* IRQ isn't used */#if 0		switch(dev->id_irq) {		case IRQ3:			t|=0x1;			break;		case IRQ5:			t|=2;			break;		case IRQ7:			t|=3;			break;		case IRQ10:			t|=4;			break;		case IRQ11:			t|=5;			break;		case IRQ12:			t|=6;			break;		case IRQ15:			t|=7;			break;

⌨️ 快捷键说明

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