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

📄 hil.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 1988 University of Utah. * Copyright (c) 1990, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * the Systems Programming Group of the University of Utah Computer * Science Department. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: Utah $Hdr: hil.c 1.38 92/01/21$ * *	@(#)hil.c	8.2 (Berkeley) 1/12/94 */#include <sys/param.h>#include <sys/conf.h>#include <sys/proc.h>#include <sys/user.h>#include <sys/ioctl.h>#include <sys/file.h>#include <sys/tty.h>#include <sys/systm.h>#include <sys/uio.h>#include <sys/kernel.h>#include <hp/dev/hilreg.h>#include <hp/dev/hilioctl.h>#include <hp/dev/hilvar.h>#include <hp/dev/kbdmap.h>#include <machine/cpu.h>#include <vm/vm_param.h>#include <vm/vm_map.h>#include <vm/vm_kern.h>#include <vm/vm_page.h>#include <vm/vm_pager.h>#ifdef hp300#define NHIL	1	/* XXX */#else#include "hil.h"#endifstruct  hilloop hilloop[NHIL];struct	_hilbell default_bell = { BELLDUR, BELLFREQ };#ifdef hp800int	hilspl;#endif#ifdef DEBUGint 	hildebug = 0;#define HDB_FOLLOW	0x01#define HDB_MMAP	0x02#define HDB_MASK	0x04#define HDB_CONFIG	0x08#define HDB_KEYBOARD	0x10#define HDB_IDMODULE	0x20#define HDB_EVENTS	0x80#endif/* symbolic sleep message strings */char hilin[] = "hilin";hilsoftinit(unit, hilbase)	int unit;	struct hil_dev *hilbase;{  	register struct hilloop *hilp = &hilloop[unit];	register int i;#ifdef DEBUG	if (hildebug & HDB_FOLLOW)		printf("hilsoftinit(%d, %x)\n", unit, hilbase);#endif	/*	 * Initialize loop information	 */	hilp->hl_addr = hilbase;	hilp->hl_cmdending = FALSE;	hilp->hl_actdev = hilp->hl_cmddev = 0;	hilp->hl_cmddone = FALSE;	hilp->hl_cmdbp = hilp->hl_cmdbuf;	hilp->hl_pollbp = hilp->hl_pollbuf;	hilp->hl_kbddev = 0;	hilp->hl_kbdlang = KBD_DEFAULT;	hilp->hl_kbdflags = 0;	/*	 * Clear all queues and device associations with queues	 */	for (i = 0; i < NHILQ; i++) {		hilp->hl_queue[i].hq_eventqueue = NULL;		hilp->hl_queue[i].hq_procp = NULL;		hilp->hl_queue[i].hq_devmask = 0;	}	for (i = 0; i < NHILD; i++)		hilp->hl_device[i].hd_qmask = 0;	hilp->hl_device[HILLOOPDEV].hd_flags = (HIL_ALIVE|HIL_PSEUDO);}hilinit(unit, hilbase)	int unit;	struct hil_dev *hilbase;{  	register struct hilloop *hilp = &hilloop[unit];#ifdef DEBUG	if (hildebug & HDB_FOLLOW)		printf("hilinit(%d, %x)\n", unit, hilbase);#endif	/*	 * Initialize software (if not already done).	 */	if ((hilp->hl_device[HILLOOPDEV].hd_flags & HIL_ALIVE) == 0)		hilsoftinit(unit, hilbase);	/*	 * Initialize hardware.	 * Reset the loop hardware, and collect keyboard/id info	 */	hilreset(hilp);	hilinfo(unit);	kbdenable(unit);}/* ARGSUSED */hilopen(dev, flags, mode, p)	dev_t dev;	int flags, mode;	struct proc *p;{  	register struct hilloop *hilp = &hilloop[HILLOOP(dev)];	register struct hilloopdev *dptr;	u_char device = HILUNIT(dev);#ifdef DEBUG	if (hildebug & HDB_FOLLOW)		printf("hilopen(%d): loop %x device %x\n",		       p->p_pid, HILLOOP(dev), device);#endif		if ((hilp->hl_device[HILLOOPDEV].hd_flags & HIL_ALIVE) == 0)		return(ENXIO);	dptr = &hilp->hl_device[device];	if ((dptr->hd_flags & HIL_ALIVE) == 0)		return(ENODEV);	/*	 * Pseudo-devices cannot be read, nothing more to do.	 */	if (dptr->hd_flags & HIL_PSEUDO)		return(0);	/*	 * Open semantics:	 * 1.	Open devices have only one of HIL_READIN/HIL_QUEUEIN.	 * 2.	HPUX processes always get read syscall interface and	 *	must have exclusive use of the device.	 * 3.	BSD processes default to shared queue interface.	 *	Multiple processes can open the device.	 */	if (p->p_md.md_flags & MDP_HPUX) {		if (dptr->hd_flags & (HIL_READIN|HIL_QUEUEIN))			return(EBUSY);		dptr->hd_flags |= HIL_READIN;	} else {		if (dptr->hd_flags & HIL_READIN)			return(EBUSY);		dptr->hd_flags |= HIL_QUEUEIN;	}	if (flags & FNONBLOCK)		dptr->hd_flags |= HIL_NOBLOCK;	/*	 * It is safe to flush the read buffer as we are guarenteed	 * that no one else is using it.	 */	ndflush(&dptr->hd_queue, dptr->hd_queue.c_cc);	send_hil_cmd(hilp->hl_addr, HIL_INTON, NULL, 0, NULL);	/*	 * Opened the keyboard, put in raw mode.	 */	(void) splhil();	if (device == hilp->hl_kbddev) {		u_char mask = 0;		send_hil_cmd(hilp->hl_addr, HIL_WRITEKBDSADR, &mask, 1, NULL);		hilp->hl_kbdflags |= KBD_RAW;#ifdef DEBUG		if (hildebug & HDB_KEYBOARD)			printf("hilopen: keyboard %d raw\n", hilp->hl_kbddev);#endif	}	(void) spl0();	return (0);}/* ARGSUSED */hilclose(dev, flags, mode, p)	dev_t dev;	int flags, mode;	struct proc *p;{  	register struct hilloop *hilp = &hilloop[HILLOOP(dev)];	register struct hilloopdev *dptr;	register int i;	u_char device = HILUNIT(dev);	char mask, lpctrl;#ifdef DEBUG	if (hildebug & HDB_FOLLOW)		printf("hilclose(%d): device %x\n", p->p_pid, device);#endif	dptr = &hilp->hl_device[device];	if (device && (dptr->hd_flags & HIL_PSEUDO))		return (0);	if (p && (p->p_md.md_flags & MDP_HPUX) == 0) {		/*		 * If this is the loop device,		 * free up all queues belonging to this process.		 */		if (device == 0) {			for (i = 0; i < NHILQ; i++)				if (hilp->hl_queue[i].hq_procp == p)					(void) hilqfree(hilp, i);		} else {			mask = ~hildevmask(device);			(void) splhil();			for (i = 0; i < NHILQ; i++)				if (hilp->hl_queue[i].hq_procp == p) {					dptr->hd_qmask &= ~hilqmask(i);					hilp->hl_queue[i].hq_devmask &= mask;				}			(void) spl0();		}	}	/*	 * Always flush the read buffer	 */	dptr->hd_flags &= ~(HIL_QUEUEIN|HIL_READIN|HIL_NOBLOCK);	ndflush(&dptr->hd_queue, dptr->hd_queue.c_cc);	/*	 * Set keyboard back to cooked mode when closed.	 */	(void) splhil();	if (device && device == hilp->hl_kbddev) {		mask = 1 << (hilp->hl_kbddev - 1);		send_hil_cmd(hilp->hl_addr, HIL_WRITEKBDSADR, &mask, 1, NULL);		hilp->hl_kbdflags &= ~(KBD_RAW|KBD_AR1|KBD_AR2);		/*		 * XXX: We have had trouble with keyboards remaining raw		 * after close due to the LPC_KBDCOOK bit getting cleared		 * somewhere along the line.  Hence we check and reset		 * LPCTRL if necessary.		 */		send_hil_cmd(hilp->hl_addr, HIL_READLPCTRL, NULL, 0, &lpctrl);		if ((lpctrl & LPC_KBDCOOK) == 0) {			printf("hilclose: bad LPCTRL %x, reset to %x\n",			       lpctrl, lpctrl|LPC_KBDCOOK);			lpctrl |= LPC_KBDCOOK;			send_hil_cmd(hilp->hl_addr, HIL_WRITELPCTRL,					&lpctrl, 1, NULL);		}#ifdef DEBUG		if (hildebug & HDB_KEYBOARD)			printf("hilclose: keyboard %d cooked\n",			       hilp->hl_kbddev);#endif		kbdenable(HILLOOP(dev));	}	(void) spl0();	return (0);}/* * Read interface to HIL device. */hilread(dev, uio)	dev_t dev;	register struct uio *uio;{	struct hilloop *hilp = &hilloop[HILLOOP(dev)];	register struct hilloopdev *dptr;	register int cc;	u_char device = HILUNIT(dev);	char buf[HILBUFSIZE];	int error;#if 0	/*	 * XXX: Don't do this since HP-UX doesn't.	 *	 * Check device number.	 * This check is necessary since loop can reconfigure.	 */	if (device > hilp->hl_maxdev)		return(ENODEV);#endif	dptr = &hilp->hl_device[device];	if ((dptr->hd_flags & HIL_READIN) == 0)		return(ENODEV);	(void) splhil();	while (dptr->hd_queue.c_cc == 0) {		if (dptr->hd_flags & HIL_NOBLOCK) {			spl0();			return(EWOULDBLOCK);		}		dptr->hd_flags |= HIL_ASLEEP;		if (error = tsleep((caddr_t)dptr, TTIPRI | PCATCH, hilin, 0)) {			(void) spl0();			return (error);		}	}	(void) spl0();	error = 0;	while (uio->uio_resid > 0 && error == 0) {		cc = hilq_to_b(&dptr->hd_queue, buf,			       min(uio->uio_resid, HILBUFSIZE));		if (cc <= 0)			break;		error = uiomove(buf, cc, uio);	}	return(error);}hilioctl(dev, cmd, data, flag, p)	dev_t dev;	int cmd, flag;	caddr_t data;	struct proc *p;{	register struct hilloop *hilp = &hilloop[HILLOOP(dev)];	char device = HILUNIT(dev);	struct hilloopdev *dptr;	register int i;	u_char hold;	int error;#ifdef DEBUG	if (hildebug & HDB_FOLLOW)		printf("hilioctl(%d): dev %x cmd %x\n",		       p->p_pid, device, cmd);#endif	dptr = &hilp->hl_device[device];	if ((dptr->hd_flags & HIL_ALIVE) == 0)		return (ENODEV);	/*	 * Don't allow hardware ioctls on virtual devices.	 * Note that though these are the BSD names, they have the same	 * values as the HP-UX equivalents so we catch them as well.	 */	if (dptr->hd_flags & HIL_PSEUDO) {		switch (cmd) {		case HILIOCSC:		case HILIOCID:		case OHILIOCID:		case HILIOCRN:		case HILIOCRS:		case HILIOCED:			return(ENODEV);		/*		 * XXX: should also return ENODEV but HP-UX compat		 * breaks if we do.  They work ok right now because		 * we only recognize one keyboard on the loop.  This		 * will have to change if we remove that restriction.		 */		case HILIOCAROFF:		case HILIOCAR1:		case HILIOCAR2:			break;		default:			break;		}	}#ifdef HPUXCOMPAT	if (p->p_md.md_flags & MDP_HPUX)		return(hpuxhilioctl(dev, cmd, data, flag));#endif	hilp->hl_cmdbp = hilp->hl_cmdbuf;	bzero((caddr_t)hilp->hl_cmdbuf, HILBUFSIZE);	hilp->hl_cmddev = device;	error = 0;	switch (cmd) {	case HILIOCSBP:		/* Send four data bytes to the tone gererator. */		send_hil_cmd(hilp->hl_addr, HIL_STARTCMD, data, 4, NULL);		/* Send the trigger beeper command to the 8042. */		send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL);		break;	case OHILIOCRRT:	case HILIOCRRT:		/* Transfer the real time to the 8042 data buffer */		send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL);		/* Read each byte of the real time */		for (i = 0; i < 5; i++) {			send_hil_cmd(hilp->hl_addr, HIL_READTIME + i, NULL,					0, &hold);			data[4-i] = hold;		}		break;			case HILIOCRT:		for (i = 0; i < 4; i++) {			send_hil_cmd(hilp->hl_addr, (cmd & 0xFF) + i,					NULL, 0, &hold);			data[i] = hold;		}		break;	case HILIOCID:	case OHILIOCID:	case HILIOCSC:	case HILIOCRN:	case HILIOCRS:	case HILIOCED:	  	send_hildev_cmd(hilp, device, (cmd & 0xFF));		bcopy(hilp->hl_cmdbuf, data, hilp->hl_cmdbp-hilp->hl_cmdbuf);	  	break;        case HILIOCAROFF:        case HILIOCAR1:        case HILIOCAR2:		if (hilp->hl_kbddev) {			hilp->hl_cmddev = hilp->hl_kbddev;			send_hildev_cmd(hilp, hilp->hl_kbddev, (cmd & 0xFF));			hilp->hl_kbdflags &= ~(KBD_AR1|KBD_AR2);			if (cmd == HILIOCAR1)				hilp->hl_kbdflags |= KBD_AR1;			else if (cmd == HILIOCAR2)				hilp->hl_kbdflags |= KBD_AR2;		}		break;	case HILIOCBEEP:		hilbeep(hilp, (struct _hilbell *)data);		break;	case FIONBIO:		dptr = &hilp->hl_device[device];		if (*(int *)data)			dptr->hd_flags |= HIL_NOBLOCK;		else			dptr->hd_flags &= ~HIL_NOBLOCK;		break;	/*	 * FIOASYNC must be present for FIONBIO above to work!	 * (See fcntl in kern_descrip.c).	 */	case FIOASYNC:		break;        case HILIOCALLOCQ:		error = hilqalloc(hilp, (struct hilqinfo *)data);		break;        case HILIOCFREEQ:		error = hilqfree(hilp, ((struct hilqinfo *)data)->qid);		break;        case HILIOCMAPQ:		error = hilqmap(hilp, *(int *)data, device);		break;        case HILIOCUNMAPQ:		error = hilqunmap(hilp, *(int *)data, device);		break;	case HILIOCHPUX:		dptr = &hilp->hl_device[device];		dptr->hd_flags |= HIL_READIN;		dptr->hd_flags &= ~HIL_QUEUEIN;		break;        case HILIOCRESET:	        hilreset(hilp);		break;		#ifdef DEBUG        case HILIOCTEST:		hildebug = *(int *) data;		break;#endif        default:		error = EINVAL;		break;	}	hilp->hl_cmddev = 0;	return(error);}#ifdef HPUXCOMPAT/* ARGSUSED */hpuxhilioctl(dev, cmd, data, flag)	dev_t dev;	int cmd, flag;	caddr_t data;{	register struct hilloop *hilp = &hilloop[HILLOOP(dev)];	char device = HILUNIT(dev);	struct hilloopdev *dptr;	register int i;	u_char hold;	hilp->hl_cmdbp = hilp->hl_cmdbuf;	bzero((caddr_t)hilp->hl_cmdbuf, HILBUFSIZE);	hilp->hl_cmddev = device;	switch (cmd) {	case HILSC:	case HILID:

⌨️ 快捷键说明

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