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

📄 winbond.c

📁 linux操作系统下的红外驱动的测试程序
💻 C
字号:
/********************************************************************* *                 * Filename:      winbond.c * Version:       0.1 * Description:   Hardware probe for Winbond infrared controllers * Status:        Experimental. * Author:        Takahide Higuchi <thiguchi@pluto.dti.ne.jp> * Created at:    Tue Jan 18 00:23:00 2000 * Modified at:   Tue Jan 18 00:35:04 2000 * Modified by:   Takahide Higuchi <thiguchi@pluto.dti.ne.jp> *  *     Copyright (c) 2000 Takahide Higuchi, All Rights Reserved. *      *     This program is free software; you can redistribute it and/or  *     modify it under the terms of the GNU General Public License as  *     published by the Free Software Foundation; either version 2 of  *     the License, or (at your option) any later version. *  *     This program is distributed in the hope that it will be useful, *     but WITHOUT ANY WARRANTY; without even the implied warranty of *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *     GNU General Public License for more details. *  *     You should have received a copy of the GNU General Public License  *     along with this program; if not, write to the Free Software  *     Foundation, Inc., 59 Temple Place, Suite 330, Boston,  *     MA 02111-1307 USA *      ********************************************************************/#include <sys/types.h>#include <stdio.h>#include <unistd.h>#include <fcntl.h>#include <asm/io.h>#include "findchip.h"#define MANUFACTURER "WINBOND"#define	CR07	0x07#define	CR09	0x09#define	CR0B	0x0B#define	CR0C	0x0C#define	CR0D	0x0D#define	CR16	0x16#define	CR20	0x20#define	CR21	0x21#define	CR25	0x25#define	CR26	0x26#define	CR28	0x28#define	CR2A	0x2A#define	CR2C	0x2C#define	CR60	0x60#define	CR61	0x61#define	CR70	0x70#define	CR74	0x74#define	CR75	0x75#define	CRF0	0xF0#define W83977_DEVICE_ID         0x97/* bitmasks */#define W83877_HEFRAS_MASK       0x01 #define W83877_HEFERE_MASK       0x20#define W83977_HEFRAS_MASK       0x40#define CHIPID                   0x0F#define IRTXDRQSEL               0xF0#define IRRXDRQSEL               0x0F#define URBIQS                   0x0F#define URBAD                    0xFE#define TXW4C                    0x40#define RXW4C                    0x20#define RXW4C_977                0x08#define TXW4C_977                0x04#define ENBKIRSL                 0x10#define URIRSEL                  0x08#define HDUPLX                   0x08#define IRMODE                   0x07#define ENBNKSEL                 0x08#define ENBNKSEL_977             0x01/* indexs */#define W83877_HEFRAS_INDEX      CR16#define W83877_HEFERE_INDEX      CR0C#define W83977_HEFRAS_INDEX      CR26#define NOT_EXIST                -1enum {	FIR_SUPPORT,	NO_FIR_SUPPORT,};enum {	W83977_PNP, /* 		       not implemented yet :		       W83977 chip will be Comply-PNP mode 		       if PIN #51 (~DTRB) is pulled up 		     */	W83977,     /* compatible-PNP mode */	W83877, };	struct winbond_chip {	char *name;	int chip_id;        /* Device Rev (CR21) for 83977s,  			       CHIP ID (CR09) for 83877s */	int fir_support;    /* SUPPORT_FIR or 0 */};struct winbond_efer {	int chip_type;  /* W83877 , W83977 or W83977_PNP */	int efer_addr;  /* address of Extended Function Enable Register */	int writes;     /* write start_flag to EFER "writes" times */ 	int start_flag;	int end_flag;   /* finally write it to EFER */ 	int efir_addr;  /* Extended Function Index Reg. */	int efdr_addr;  /* Extended Function Data Reg. */	int hefras_index;     /* Register index of HEFERE bit */	int hefras_mask;      /* bitmask for HEFERE */	int hefras;           /* HEFRAS bit should be (1 or 0) */	/*  if hefere_index == -1, HEFERE will be ignored */	int hefere_index;     /* Register index of HEFERE bit */	int hefere_mask;      /* bitmask for HEFERE */	int hefere;           /* HEFERE bit should be (1 or 0) */};typedef struct winbond_chip winbond_chip_t;typedef struct winbond_efer winbond_efer_t;static winbond_chip_t chips[] = {	{ "W83977TF", 0x73,  NO_FIR_SUPPORT}, 	{ "W83977ATF", 0x74, FIR_SUPPORT}, 	{ "W83877AF",  0x0b, FIR_SUPPORT},	{ "W83877TF",  0x0c, NO_FIR_SUPPORT},	{ "W83877ATF",  0x0d, FIR_SUPPORT},/*    Entries below here are not well confirmed.   if you have one of these chips, please mail me an output of    "findchip -d -v WINBOND". *//*	{ "W83977F/AF", 0x71, FIR_SUPPORT }, */ /* 	{ "W83877F",  0x0a, NO_FIR_SUPPORT}, */	{ NULL }};static winbond_efer_t efers[] = {	{ W83977,	  0x3F0, 2, 0x87 ,0xAA, 0x3F0, 0x3F1, 	  W83977_HEFRAS_INDEX, W83977_HEFRAS_MASK, 0,	  NOT_EXIST, 0 ,0 },  	{ W83977,	  0x370, 2, 0x87 ,0xAA, 0x370, 0x371, 	  W83977_HEFRAS_INDEX, W83977_HEFRAS_MASK, 1,	  NOT_EXIST, 0 ,0 },	{ W83877,	  0x250, 1, 0x88 ,0x88, 0x251, 0x252,	  W83877_HEFRAS_INDEX, W83877_HEFRAS_MASK, 0,	  W83877_HEFERE_INDEX, W83877_HEFERE_MASK, 0 },	{ W83877,	  0x250, 1, 0x89 ,0x89, 0x251, 0x252,	  W83877_HEFRAS_INDEX, W83877_HEFRAS_MASK, 0,	  W83877_HEFERE_INDEX, W83877_HEFERE_MASK, 1 },	{ W83877,	  0x3F0, 2, 0x86 ,0xAA, 0x3F0, 0x3F1,	  W83877_HEFRAS_INDEX, W83877_HEFRAS_MASK, 1,	  W83877_HEFERE_INDEX, W83877_HEFERE_MASK, 0 },	{ W83877,	  0x3F0, 2, 0x87 ,0xAA, 0x3F0, 0x3F1,	  W83877_HEFRAS_INDEX, W83877_HEFRAS_MASK, 1,	  W83877_HEFERE_INDEX, W83877_HEFERE_MASK, 1 },	{ 0 }};/* * Function w83977_read_info() * *    if Chip ID is valid, return non-zero * */int w83977_read_info(winbond_efer_t *eferinfo){	struct chip_info info;	winbond_chip_t *chipinfo;	int rxdma, txdma, devid, revision, misc;	devid = 0;		outb( CR20, eferinfo->efir_addr);	devid = (inb(eferinfo->efdr_addr));			outb( CR21, eferinfo->efir_addr);	revision = (inb(eferinfo->efdr_addr));	DEBUG("chip id = 0x%02x, revision = 0x%02x\n", devid, revision);	if(devid != W83977_DEVICE_ID) 	{		DEBUG("Wrong device ID = 0x%02x\n", devid);		return 0;	}	for(chipinfo = chips; chipinfo->name; chipinfo++){		if (revision == chipinfo->chip_id)			break;	}	if(chipinfo->name == NULL){		DEBUG("Device Revision is 0x%02x :" 		      "no known chip was detected.\n", revision);		return 0;	}	info.chip_id = devid;	info.revision = revision;	DEBUG("Device Revision 0x%02x : %s is detected!\n",	      info.chip_id, chipinfo->name);	if(chipinfo->fir_support != FIR_SUPPORT)		DEBUG("this chip does not have FIR block.n");	/* select a logical device */	outb( CR07, eferinfo->efir_addr);	outb( 0x06 ,eferinfo->efdr_addr);  /* FIR block */	/* read DMA settings */	outb(CR74, eferinfo->efir_addr);	rxdma = inb(eferinfo->efdr_addr);	if(rxdma > 3){		DEBUG(" RX DMA is inactive\n");				rxdma = -1;	}	outb(CR75, eferinfo->efir_addr);	txdma = inb(eferinfo->efdr_addr);	if(txdma > 3){		DEBUG(" TX DMA is inactive, or single DMA mode\n");				txdma = -1;	}	info.dma = rxdma;	/* read IRQ settings */	outb(CR70, eferinfo->efir_addr);	info.irq = inb(eferinfo->efdr_addr) & 0x0f;	/* read I/O base address */	outb(CR60, eferinfo->efir_addr);	info.sir_base = (inb(eferinfo->efdr_addr) << 8);	outb(CR61, eferinfo->efir_addr);	info.sir_base |= (inb(eferinfo->efdr_addr) & 0xff);	info.fir_base = info.sir_base ;  	info.manufacturer = MANUFACTURER;	info.name = chipinfo->name;	info.cfg_base = eferinfo->efer_addr;	info.uart_comp = 1;      /*  we knows it :) */		/* read misc (no! very important) settings */	outb(CRF0, eferinfo->efir_addr);	misc = inb(eferinfo->efdr_addr) ;	if(misc & TXW4C_977)		DEBUG(" RX->TX Turn around delay(4 char time) is enabled\n");	else		DEBUG(" RX->TX Turn around delay(4 char time) is disabled\n");		if(misc & RXW4C_977)		DEBUG(" TX->RX Turn around delay(4 char time) is enabled\n");	else		DEBUG(" TX->RX Turn around delay(4 char time) is disabled\n");	if(misc & ENBNKSEL_977)	{		DEBUG(" Bank selection si enabled.\n");		info.enabled = 1;	} else {		DEBUG(" Bank selection is disabled(CRF0 = 0x%02x).\n", misc);		info.enabled = 0;	}	info.suspended = 0;   /* todo: handling of this */	print_info(&info);	return 1;}/* * Function winbond_read_info() * *    if Chip ID is valid, return non-zero * */int w83877_read_info(winbond_efer_t *eferinfo){	struct chip_info info;	winbond_chip_t *chipinfo;	int rxdma, txdma, chipid, misc;	int disabled = 0;	/* find chip_ID */	outb( CR09, eferinfo->efir_addr);	chipid = (inb(eferinfo->efdr_addr)) & CHIPID;		for(chipinfo = chips; chipinfo->name; chipinfo++){		if (chipid == chipinfo->chip_id)			break;	}	if(chipinfo->name == NULL){		DEBUG("chip ID is 0x%02x : no known chip was detected.\n",		      chipid);		return 0;	}	info.chip_id = chipid;	DEBUG("chip ID is 0x%02x : %s is detected!\n",	      info.chip_id, chipinfo->name);	if(chipinfo->fir_support != FIR_SUPPORT)		DEBUG("this chip does not have FIR block.n");			/* read DMA settings */	outb(CR2A, eferinfo->efir_addr);	rxdma = inb(eferinfo->efdr_addr);	txdma = (rxdma & IRTXDRQSEL) >> 4;	rxdma &= IRRXDRQSEL;	DEBUG(" RX DMA = %d, TX DMA = %d\n", rxdma, txdma);	if( txdma == rxdma )		info.dma = txdma;	else	{		if(txdma !=0)			/* todo: redefinition of chip_info ? */			DEBUG(" -- Configured for Dual DMA mode\n");	}	if(info.dma == 0)		DEBUG("  -- DMA is disabled.\n");			/* read IRQ settings */	outb(CR28, eferinfo->efir_addr);	info.irq = inb(eferinfo->efdr_addr) & URBIQS;	outb(CR25, eferinfo->efir_addr);	info.sir_base = (inb(eferinfo->efdr_addr) & URBAD) << 2;	info.fir_base = info.sir_base ;  	info.manufacturer = MANUFACTURER;	info.name = chipinfo->name;	info.cfg_base = eferinfo->efer_addr;	info.uart_comp = 1;      /*  we knows it :) */	/* read misc (no! very important) settings */	outb(CR0B, eferinfo->efir_addr);	misc = inb(eferinfo->efdr_addr) ;	if(misc & TXW4C)		DEBUG(" RX->TX Turn around delay(4 char time) is enabled\n");	else		DEBUG(" RX->TX Turn around delay(4 char time) is disabled\n");		if(misc & RXW4C)		DEBUG(" TX->RX Turn around delay(4 char time) is enabled\n");	else		DEBUG(" TX->RX Turn around delay(4 char time) is disabled\n");		outb(CR0C, eferinfo->efir_addr);	misc = inb(eferinfo->efdr_addr) ;	if(misc & ENBKIRSL)		DEBUG(" Config Registers for IR functions are activated. good.\n");	else {		DEBUG(" Config Registers for IR functions are "		      "inactivated(CR0C = 0x%02x).\n", misc);		disabled = 1;	}		if(misc & URIRSEL)		DEBUG(" UART B is IR mode. \n");	else {		DEBUG(" UART B is not IR mode(CR0C = 0x%02x). \n",misc);		disabled = 1;	}		outb(CR0D, eferinfo->efir_addr);	misc = inb(eferinfo->efdr_addr) ;	if(misc & HDUPLX)		DEBUG(" Configured for Half-Duplex\n");	else		DEBUG(" Configured for Full-Duplex\n");	switch(misc & IRMODE){	case 0:	case 1:		DEBUG(" IR support are disabled. bad.\n");		disabled = 1;		break;		case 2:		DEBUG(" Configured for IrDA. (SIR pulse width = 1.6us)\n");		break;	case 3:		DEBUG(" Configured for IrDA. (SIR pulse width = 3/16)\n");		break;	default:		DEBUG(" Configured for ASK-IR(0x%02x). \n",misc & IRMODE);		disabled = 1;		break;	}		outb(CR2C, eferinfo->efir_addr);	misc = inb(eferinfo->efdr_addr);	if(misc & ENBNKSEL)		DEBUG(" Bank selection is enabled. \n");	else {		DEBUG(" Bank selection is disabled(CR2C = 0x%02x)\n",misc);		disabled = 1;	}		if(disabled){		info.enabled = 0;	}	else		info.enabled = 1;	/*	  I think we should not read revision number because it resides in 	  Advanced UART, which may be activated as a normal UART by	  the Linux kernel. once I've tried to read the number, but 	  kernel got frozen :<	  note:	  Device ID and Device Rev do not exist in EFRs 	  because W83877 is not ISA-PNP spec compliant	*/	info.revision = -1;	info.suspended = 0;   /* todo: handling of this */	print_info(&info);	return 1; /* found */}/* * Function probe_winbond () * *     * */int probe_winbond(void){	int found = 0;	winbond_efer_t *eferinfo;	int i, hefras, hefere;	/* search for the address of EFIR. */	for (eferinfo = efers; eferinfo->efer_addr && found == 0; eferinfo++) {		DEBUG("Probing for EFER at 0x%04x ...\n", eferinfo->efer_addr);		/* knock EFER */		for (i = 0; i < eferinfo->writes; i++){			outb( eferinfo->start_flag, eferinfo->efer_addr);		}		if(eferinfo->hefras_index >= 0)		{			outb( eferinfo->hefras_index, eferinfo->efir_addr);			hefras = (inb(eferinfo->efdr_addr));			DEBUG("hefras = 0x%02x \n", hefras);			hefras = (hefras & eferinfo->hefras_mask) ? 1 : 0;			if(hefras != eferinfo->hefras)				goto skip;		}		if(eferinfo->hefere_index >= 0)		{			outb( eferinfo->hefere_index, eferinfo->efir_addr);			hefere = (inb(eferinfo->efdr_addr));			DEBUG("hefere = 0x%02x \n", hefere);			hefere = (hefere & eferinfo->hefere_mask) ? 1 : 0;			if(hefere != eferinfo->hefere)				goto skip;		}		DEBUG("EFER seems to be probed at 0x%04x\n",		      eferinfo->efer_addr);		switch(eferinfo->chip_type){		case W83877:			found = w83877_read_info(eferinfo);			break;		case W83977:						found = w83977_read_info(eferinfo);			break;		default:			DEBUG("BUG in the source code.. :(");			break;		}	skip:		outb( eferinfo->end_flag, eferinfo->efer_addr);		if(found)			return 0;	}	DEBUG("Couldn't find Winbond superI/O chip.\n");	return 0;}

⌨️ 快捷键说明

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