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

📄 hil.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* Enable interrupts */	send_hil_cmd(hildevice, HIL_INTON, NULL, 0, NULL);}kbddisable(unit)	int unit;{}/* * XXX: read keyboard directly and return code. * Used by console getchar routine.  Could really screw up anybody * reading from the keyboard in the normal, interrupt driven fashion. */kbdgetc(unit, statp)	int unit, *statp;{	struct hilloop *hilp = &hilloop[unit];	register struct hil_dev *hildevice = hilp->hl_addr;	register int c, stat;	int s;	s = splhil();	while (((stat = READHILSTAT(hildevice)) & HIL_DATA_RDY) == 0)		;	c = READHILDATA(hildevice);	splx(s);	*statp = stat;	return(c);}/* * Recoginize and clear keyboard generated NMIs. * Returns 1 if it was ours, 0 otherwise.  Note that we cannot use * send_hil_cmd() to issue the clear NMI command as that would actually * lower the priority to splimp() and it doesn't wait for the completion * of the command.  Either of these conditions could result in the * interrupt reoccuring.  Note that we issue the CNMT command twice. * This seems to be needed, once is not always enough!?! */kbdnmi(unit)	int unit;{#ifdef hp300	struct hilloop *hilp = &hilloop[0]; /* XXX how do we know on 300? */#else	struct hilloop *hilp = &hilloop[unit];#endif#ifdef hp300	if ((*KBDNMISTAT & KBDNMI) == 0)		return(0);#endif	HILWAIT(hilp->hl_addr);	WRITEHILCMD(hilp->hl_addr, HIL_CNMT);	HILWAIT(hilp->hl_addr);	WRITEHILCMD(hilp->hl_addr, HIL_CNMT);	HILWAIT(hilp->hl_addr);	return(1);}#define HILSECURITY	0x33#define HILIDENTIFY	0x03#define HILSCBIT	0x04/* * Called at boot time to print out info about interesting devices */hilinfo(unit)	int unit;{  	register struct hilloop *hilp = &hilloop[unit];	register int id, len;	register struct kbdmap *km;	/*	 * Keyboard info.	 */	if (hilp->hl_kbddev) {		printf("hil%d: ", hilp->hl_kbddev);		for (km = kbd_map; km->kbd_code; km++)			if (km->kbd_code == hilp->hl_kbdlang) {				printf("%s ", km->kbd_desc);				break;			}		printf("keyboard\n");	}	/*	 * ID module.	 * Attempt to locate the first ID module and print out its	 * security code.  Is this a good idea??	 */	id = hiliddev(hilp);	if (id) {		hilp->hl_cmdbp = hilp->hl_cmdbuf;		hilp->hl_cmddev = id;		send_hildev_cmd(hilp, id, HILSECURITY);		len = hilp->hl_cmdbp - hilp->hl_cmdbuf;		hilp->hl_cmdbp = hilp->hl_cmdbuf;		hilp->hl_cmddev = 0;		printf("hil%d: security code", id);		for (id = 0; id < len; id++)			printf(" %x", hilp->hl_cmdbuf[id]);		while (id++ < 16)			printf(" 0");		printf("\n");	}}#define HILAR1	0x3E#define HILAR2	0x3F/* * Called after the loop has reconfigured.  Here we need to: *	- determine how many devices are on the loop *	  (some may have been added or removed) *	- locate the ITE keyboard (if any) and ensure *	  that it is in the proper state (raw or cooked) *	  and is set to use the proper language mapping table *	- ensure all other keyboards are raw * Note that our device state is now potentially invalid as * devices may no longer be where they were.  What we should * do here is either track where the devices went and move * state around accordingly or, more simply, just mark all * devices as HIL_DERROR and don't allow any further use until * they are closed.  This is a little too brutal for my tastes, * we prefer to just assume people won't move things around. */hilconfig(hilp)	register struct hilloop *hilp;{	u_char db;	int s;	s = splhil();#ifdef DEBUG	if (hildebug & HDB_CONFIG) {		printf("hilconfig: reconfigured: ");		send_hil_cmd(hilp->hl_addr, HIL_READLPSTAT, NULL, 0, &db);		printf("LPSTAT %x, ", db);		send_hil_cmd(hilp->hl_addr, HIL_READLPCTRL, NULL, 0, &db);		printf("LPCTRL %x, ", db);		send_hil_cmd(hilp->hl_addr, HIL_READKBDSADR, NULL, 0, &db);		printf("KBDSADR %x\n", db);		hilreport(hilp);	}#endif	/*	 * Determine how many devices are on the loop.	 * Mark those as alive and real, all others as dead.	 */	db = 0;	send_hil_cmd(hilp->hl_addr, HIL_READLPSTAT, NULL, 0, &db);	hilp->hl_maxdev = db & LPS_DEVMASK;#ifdef DEBUG	if (hildebug & HDB_CONFIG)		printf("hilconfig: %d devices found\n", hilp->hl_maxdev);#endif	for (db = 1; db < NHILD; db++) {		if (db <= hilp->hl_maxdev)			hilp->hl_device[db].hd_flags |= HIL_ALIVE;		else			hilp->hl_device[db].hd_flags &= ~HIL_ALIVE;		hilp->hl_device[db].hd_flags &= ~HIL_PSEUDO;	}#ifdef DEBUG	if (hildebug & (HDB_CONFIG|HDB_KEYBOARD))		printf("hilconfig: max device %d\n", hilp->hl_maxdev);#endif	if (hilp->hl_maxdev == 0) {		hilp->hl_kbddev = 0;		splx(s);		return;	}	/*	 * Find out where the keyboards are and record the ITE keyboard	 * (first one found).  If no keyboards found, we are all done.	 */	db = 0;	send_hil_cmd(hilp->hl_addr, HIL_READKBDSADR, NULL, 0, &db);#ifdef DEBUG	if (hildebug & HDB_KEYBOARD)		printf("hilconfig: keyboard: KBDSADR %x, old %d, new %d\n",		       db, hilp->hl_kbddev, ffs((int)db));#endif	hilp->hl_kbddev = ffs((int)db);	if (hilp->hl_kbddev == 0) {		splx(s);		return;	}	/*	 * Determine if the keyboard should be cooked or raw and configure it.	 */	db = (hilp->hl_kbdflags & KBD_RAW) ? 0 : 1 << (hilp->hl_kbddev - 1);	send_hil_cmd(hilp->hl_addr, HIL_WRITEKBDSADR, &db, 1, NULL);	/*	 * Re-enable autorepeat in raw mode, cooked mode AR is not affected.	 */	if (hilp->hl_kbdflags & (KBD_AR1|KBD_AR2)) {		db = (hilp->hl_kbdflags & KBD_AR1) ? HILAR1 : HILAR2;		hilp->hl_cmddev = hilp->hl_kbddev;		send_hildev_cmd(hilp, hilp->hl_kbddev, db);		hilp->hl_cmddev = 0;	}	/*	 * Determine the keyboard language configuration, but don't	 * override a user-specified setting.	 */	db = 0;	send_hil_cmd(hilp->hl_addr, HIL_READKBDLANG, NULL, 0, &db);#ifdef DEBUG	if (hildebug & HDB_KEYBOARD)		printf("hilconfig: language: old %x new %x\n",		       hilp->hl_kbdlang, db);#endif	if (hilp->hl_kbdlang != KBD_SPECIAL) {		struct kbdmap *km;		for (km = kbd_map; km->kbd_code; km++)			if (km->kbd_code == db) {				hilp->hl_kbdlang = db;				/* XXX */				kbd_keymap = km->kbd_keymap;				kbd_shiftmap = km->kbd_shiftmap;				kbd_ctrlmap = km->kbd_ctrlmap;				kbd_ctrlshiftmap = km->kbd_ctrlshiftmap;				kbd_stringmap = km->kbd_stringmap;			}	}	splx(s);}hilreset(hilp)	struct hilloop *hilp;{	register struct hil_dev *hildevice = hilp->hl_addr;	u_char db;#ifdef DEBUG	if (hildebug & HDB_FOLLOW)		printf("hilreset(%x)\n", hilp);#endif	/*	 * Initialize the loop: reconfigure, don't report errors,	 * cook keyboards, and enable autopolling.	 */	db = LPC_RECONF | LPC_KBDCOOK | LPC_NOERROR | LPC_AUTOPOLL;	send_hil_cmd(hildevice, HIL_WRITELPCTRL, &db, 1, NULL);	/*	 * Delay one second for reconfiguration and then read the the	 * data register to clear the interrupt (if the loop reconfigured).	 */	DELAY(1000000);	if (READHILSTAT(hildevice) & HIL_DATA_RDY)		db = READHILDATA(hildevice);	/*	 * The HIL loop may have reconfigured.  If so we proceed on,	 * if not we loop until a successful reconfiguration is reported	 * back to us.  The HIL loop will continue to attempt forever.	 * Probably not very smart.	 */	do {		send_hil_cmd(hildevice, HIL_READLPSTAT, NULL, 0, &db);        } while ((db & (LPS_CONFFAIL|LPS_CONFGOOD)) == 0);	/*	 * At this point, the loop should have reconfigured.	 * The reconfiguration interrupt has already called hilconfig()	 * so the keyboard has been determined.	 */	send_hil_cmd(hildevice, HIL_INTON, NULL, 0, NULL);}hilbeep(hilp, bp)	struct hilloop *hilp;	register struct _hilbell *bp;{	u_char buf[2];	buf[0] = ~((bp->duration - 10) / 10);	buf[1] = bp->frequency;	send_hil_cmd(hilp->hl_addr, HIL_SETTONE, buf, 2, NULL);}/* * Locate and return the address of the first ID module, 0 if none present. */hiliddev(hilp)	register struct hilloop *hilp;{	register int i, len;#ifdef DEBUG	if (hildebug & HDB_IDMODULE)		printf("hiliddev(%x): max %d, looking for idmodule...",		       hilp, hilp->hl_maxdev);#endif	for (i = 1; i <= hilp->hl_maxdev; i++) {		hilp->hl_cmdbp = hilp->hl_cmdbuf;		hilp->hl_cmddev = i;		send_hildev_cmd(hilp, i, HILIDENTIFY);		/*		 * XXX: the final condition checks to ensure that the		 * device ID byte is in the range of the ID module (0x30-0x3F)		 */		len = hilp->hl_cmdbp - hilp->hl_cmdbuf;		if (len > 1 && (hilp->hl_cmdbuf[1] & HILSCBIT) &&		    (hilp->hl_cmdbuf[0] & 0xF0) == 0x30) {			hilp->hl_cmdbp = hilp->hl_cmdbuf;			hilp->hl_cmddev = i;			send_hildev_cmd(hilp, i, HILSECURITY);			break;		}	}			hilp->hl_cmdbp = hilp->hl_cmdbuf;	hilp->hl_cmddev = 0;#ifdef DEBUG	if (hildebug & HDB_IDMODULE)		if (i <= hilp->hl_maxdev)			printf("found at %d\n", i);		else			printf("not found\n");#endif	return(i <= hilp->hl_maxdev ? i : 0);}#ifdef HPUXCOMPAT/* * XXX map devno as expected by HP-UX */hildevno(dev)	dev_t dev;{	int newdev;	newdev = 24 << 24;#ifdef HILCOMPAT	/*	 * XXX compat check	 * Don't convert old style specfiles already in correct format	 */	if (minor(dev) && (dev & 0xF) == 0)		newdev |= minor(dev);	else#endif	newdev |= (HILLOOP(dev) << 8) | (HILUNIT(dev) << 4);	return(newdev);}#endif/* * Low level routines which actually talk to the 8042 chip. *//* * Send a command to the 8042 with zero or more bytes of data. * If rdata is non-null, wait for and return a byte of data. * We run at splimp() to make the transaction as atomic as * possible without blocking the clock (is this necessary?) */send_hil_cmd(hildevice, cmd, data, dlen, rdata)	register struct hil_dev *hildevice;	u_char cmd, *data, dlen;	u_char *rdata;{	u_char status;	int s = splimp();	HILWAIT(hildevice);	WRITEHILCMD(hildevice, cmd);	while (dlen--) {	  	HILWAIT(hildevice);		WRITEHILDATA(hildevice, *data++);	}	if (rdata) {		do {			HILDATAWAIT(hildevice);			status = READHILSTAT(hildevice);			*rdata = READHILDATA(hildevice);		} while (((status >> HIL_SSHIFT) & HIL_SMASK) != HIL_68K);	}	splx(s);}/* * Send a command to a device on the loop. * Since only one command can be active on the loop at any time, * we must ensure that we are not interrupted during this process. * Hence we mask interrupts to prevent potential access from most * interrupt routines and turn off auto-polling to disable the * internally generated poll commands. * * splhigh is extremely conservative but insures atomic operation, * splimp (clock only interrupts) seems to be good enough in practice. */send_hildev_cmd(hilp, device, cmd)	register struct hilloop *hilp;	char device, cmd;{	register struct hil_dev *hildevice = hilp->hl_addr;	u_char status, c;	int s = splimp();	polloff(hildevice);	/*	 * Transfer the command and device info to the chip	 */	HILWAIT(hildevice);	WRITEHILCMD(hildevice, HIL_STARTCMD);  	HILWAIT(hildevice);	WRITEHILDATA(hildevice, 8 + device);  	HILWAIT(hildevice);	WRITEHILDATA(hildevice, cmd);  	HILWAIT(hildevice);	WRITEHILDATA(hildevice, HIL_TIMEOUT);	/*	 * Trigger the command and wait for completion	 */	HILWAIT(hildevice);	WRITEHILCMD(hildevice, HIL_TRIGGER);	hilp->hl_cmddone = FALSE;	do {		HILDATAWAIT(hildevice);		status = READHILSTAT(hildevice);		c = READHILDATA(hildevice);		hil_process_int(hilp, status, c);	} while (!hilp->hl_cmddone);	pollon(hildevice);	splx(s);}/* * Turn auto-polling off and on. * Also disables and enable auto-repeat.  Why? */polloff(hildevice)	register struct hil_dev *hildevice;{	register char db;	/*	 * Turn off auto repeat	 */	HILWAIT(hildevice);	WRITEHILCMD(hildevice, HIL_SETARR);	HILWAIT(hildevice);	WRITEHILDATA(hildevice, 0);	/*	 * Turn off auto-polling	 */	HILWAIT(hildevice);	WRITEHILCMD(hildevice, HIL_READLPCTRL);	HILDATAWAIT(hildevice);	db = READHILDATA(hildevice);	db &= ~LPC_AUTOPOLL;	HILWAIT(hildevice);	WRITEHILCMD(hildevice, HIL_WRITELPCTRL);	HILWAIT(hildevice);	WRITEHILDATA(hildevice, db);	/*	 * Must wait til polling is really stopped	 */	do {			HILWAIT(hildevice);		WRITEHILCMD(hildevice, HIL_READBUSY);		HILDATAWAIT(hildevice);		db = READHILDATA(hildevice);	} while (db & BSY_LOOPBUSY);}pollon(hildevice)	register struct hil_dev *hildevice;{	register char db;	/*	 * Turn on auto polling	 */	HILWAIT(hildevice);	WRITEHILCMD(hildevice, HIL_READLPCTRL);	HILDATAWAIT(hildevice);	db = READHILDATA(hildevice);	db |= LPC_AUTOPOLL;	HILWAIT(hildevice);	WRITEHILCMD(hildevice, HIL_WRITELPCTRL);	HILWAIT(hildevice);	WRITEHILDATA(hildevice, db);	/*	 * Turn on auto repeat	 */	HILWAIT(hildevice);	WRITEHILCMD(hildevice, HIL_SETARR);	HILWAIT(hildevice);	WRITEHILDATA(hildevice, ar_format(KBD_ARR));}#ifdef DEBUGprinthilpollbuf(hilp)	register struct hilloop *hilp;{  	register u_char *cp;	register int i, len;	cp = hilp->hl_pollbuf;	len = hilp->hl_pollbp - cp;	for (i = 0; i < len; i++)		printf("%x ", hilp->hl_pollbuf[i]);	printf("\n");}printhilcmdbuf(hilp)	register struct hilloop *hilp;{  	register u_char *cp;	register int i, len;	cp = hilp->hl_cmdbuf;	len = hilp->hl_cmdbp - cp;	for (i = 0; i < len; i++)		printf("%x ", hilp->hl_cmdbuf[i]);	printf("\n");}hilreport(hilp)	register struct hilloop *hilp;{	register int i, len;	int s = splhil();	for (i = 1; i <= hilp->hl_maxdev; i++) {		hilp->hl_cmdbp = hilp->hl_cmdbuf;		hilp->hl_cmddev = i;		send_hildev_cmd(hilp, i, HILIDENTIFY);		printf("hil%d: id: ", i);		printhilcmdbuf(hilp);		len = hilp->hl_cmdbp - hilp->hl_cmdbuf;		if (len > 1 && (hilp->hl_cmdbuf[1] & HILSCBIT)) {			hilp->hl_cmdbp = hilp->hl_cmdbuf;			hilp->hl_cmddev = i;			send_hildev_cmd(hilp, i, HILSECURITY);			printf("hil%d: sc: ", i);			printhilcmdbuf(hilp);		}	}			hilp->hl_cmdbp = hilp->hl_cmdbuf;	hilp->hl_cmddev = 0;	splx(s);}#endif

⌨️ 快捷键说明

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