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

📄 isapnp.c

📁 话带数据中传真解调程序
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *  ISA Plug & Play support *  Copyright (c) by Jaroslav Kysela <perex@suse.cz> * *  Version 0.1.0 * *  Modified by Ed Okerson <eokerson@quicknet.net> to work with the 2.2.x *  series of Linux kernels. 11/17/99 * *   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., 675 Mass Ave, Cambridge, MA 02139, USA. * */#include <linux/config.h>#include <linux/version.h>#define EXPORT_SYMTAB#include <linux/module.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/ioport.h>#include <linux/string.h>#include <linux/malloc.h>#include <linux/proc_fs.h>#include <linux/delay.h>#include <asm/io.h>#include <asm/dma.h>#include <asm/irq.h>#include <linux/pci.h>#include <linux/vmalloc.h>#include <linux/poll.h>#include <linux/init.h>#include <asm/uaccess.h>#include "pnpio.h"#include "isapnp.h"#ifdef CONFIG_PROC_FS#include "isapnp_proc.c"#endif#if 0#define ISAPNP_REGION_OK#endif#if 0#define ISAPNP_DEBUG#endif//struct resource *pidxr_res = NULL;//struct resource *pnpwrp_res = NULL;//struct resource *isapnp_rdp_res = NULL;int isapnp_disable = 0;			/* Disable ISA PnP */int isapnp_rdp = 0;			/* Read Data Port */int isapnp_reset = 0;			/* reset all PnP cards (deactivate) */int isapnp_skip_pci_scan = 0;		/* skip PCI resource scanning */int isapnp_verbose = 1;			/* verbose mode */int isapnp_reserve_irq[16] = { [0 ... 15] = -1 };	/* reserve (don't use) some IRQ */int isapnp_reserve_dma[8] = { [0 ... 7] = -1 };		/* reserve (don't use) some DMA */int isapnp_reserve_io[16] = { [0 ... 15] = -1 };	/* reserve (don't use) some I/O region */int isapnp_reserve_mem[16] = { [0 ... 15] = -1 };	/* reserve (don't use) some memory region */MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");MODULE_DESCRIPTION("Generic ISA Plug & Play support");MODULE_PARM(isapnp_disable, "i");MODULE_PARM_DESC(isapnp_disable, "ISA Plug & Play disable");MODULE_PARM(isapnp_rdp, "i");MODULE_PARM_DESC(isapnp_rdp, "ISA Plug & Play read data port");MODULE_PARM(isapnp_reset, "i");MODULE_PARM_DESC(isapnp_reset, "ISA Plug & Play reset all cards");MODULE_PARM(isapnp_skip_pci_scan, "i");MODULE_PARM_DESC(isapnp_skip_pci_scan, "ISA Plug & Play skip PCI resource scanning");MODULE_PARM(isapnp_verbose, "i");MODULE_PARM_DESC(isapnp_verbose, "ISA Plug & Play verbose mode");MODULE_PARM(isapnp_reserve_irq, "1-16i");MODULE_PARM_DESC(isapnp_reserve_irq, "ISA Plug & Play - reserve IRQ line(s)");MODULE_PARM(isapnp_reserve_dma, "1-8i");MODULE_PARM_DESC(isapnp_reserve_dma, "ISA Plug & Play - reserve DMA channel(s)");MODULE_PARM(isapnp_reserve_io, "1-16i");MODULE_PARM_DESC(isapnp_reserve_io, "ISA Plug & Play - reserve I/O region(s) - port,size");MODULE_PARM(isapnp_reserve_mem, "1-16i");MODULE_PARM_DESC(isapnp_reserve_mem, "ISA Plug & Play - reserve memory region(s) - address,size");#define _PIDXR		0x279#define _PNPWRP		0xa79/* short tags */#define _STAG_PNPVERNO		0x01#define _STAG_LOGDEVID		0x02#define _STAG_COMPATDEVID	0x03#define _STAG_IRQ		0x04#define _STAG_DMA		0x05#define _STAG_STARTDEP		0x06#define _STAG_ENDDEP		0x07#define _STAG_IOPORT		0x08#define _STAG_FIXEDIO		0x09#define _STAG_VENDOR		0x0e#define _STAG_END		0x0f/* long tags */#define _LTAG_MEMRANGE		0x81#define _LTAG_ANSISTR		0x82#define _LTAG_UNICODESTR	0x83#define _LTAG_VENDOR		0x84#define _LTAG_MEM32RANGE	0x85#define _LTAG_FIXEDMEM32RANGE	0x86struct pnp_bus *isapnp_cards = NULL;	/* ISA PnP cards */struct pnp_dev *isapnp_devices = NULL;	/* ISA PnP devices */static struct pnp_dev *isapnp_last_device = NULL;static unsigned char isapnp_checksum_value;static struct semaphore isapnp_cfg_mutex = MUTEX;static int isapnp_detected = 0;/* some prototypes */static int isapnp_config_prepare(struct pnp_dev *dev);static int isapnp_config_activate(struct pnp_dev *dev);static int isapnp_config_deactivate(struct pnp_dev *dev);static inline void write_data(unsigned char x){	outb(x, _PNPWRP);}static inline void write_address(unsigned char x){	outb(x, _PIDXR);	udelay(10);}static inline unsigned char read_data(void){	unsigned char val = inb(isapnp_rdp);	return val;}unsigned char isapnp_read_byte(unsigned char idx){	write_address(idx);	return read_data();}unsigned short isapnp_read_word(unsigned char idx){	unsigned short val;	val = isapnp_read_byte(idx);	val = (val << 8) + isapnp_read_byte(idx+1);	return val;}unsigned int isapnp_read_dword(unsigned char idx){	unsigned int val;	val = isapnp_read_byte(idx);	val = (val << 8) + isapnp_read_byte(idx+1);	val = (val << 8) + isapnp_read_byte(idx+2);	val = (val << 8) + isapnp_read_byte(idx+3);	return val;}void isapnp_write_byte(unsigned char idx, unsigned char val){	write_address(idx);	write_data(val);}void isapnp_write_word(unsigned char idx, unsigned short val){	isapnp_write_byte(idx, val >> 8);	isapnp_write_byte(idx+1, val);}void isapnp_write_dword(unsigned char idx, unsigned int val){	isapnp_write_byte(idx, val >> 24);	isapnp_write_byte(idx+1, val >> 16);	isapnp_write_byte(idx+2, val >> 8);	isapnp_write_byte(idx+3, val);}static void *isapnp_alloc(long size){	void *result;	result = kmalloc(size, GFP_KERNEL);	if (!result)		return NULL;	memset(result, 0, size);	return result;}static void isapnp_key(void){	unsigned char code = 0x6a, msb;	int i;	mdelay(1);	write_address(0x00);	write_address(0x00);	write_address(code);	for (i = 1; i < 32; i++) {		msb = ((code & 0x01) ^ ((code & 0x02) >> 1)) << 7;		code = (code >> 1) | msb;		write_address(code);	}}/* place all pnp cards in wait-for-key state */static void isapnp_wait(void){	isapnp_write_byte(0x02, 0x02);}void isapnp_wake(unsigned char csn){	isapnp_write_byte(0x03, csn);}void isapnp_device(unsigned char logdev){	isapnp_write_byte(0x07, logdev);}void isapnp_activate(unsigned char logdev){	isapnp_device(logdev);	isapnp_write_byte(ISAPNP_CFG_ACTIVATE, 1);	udelay(250);}void isapnp_deactivate(unsigned char logdev){	isapnp_device(logdev);	isapnp_write_byte(ISAPNP_CFG_ACTIVATE, 0);}static void __init isapnp_peek(unsigned char *data, int bytes){	int i, j;	unsigned char d;	for (i = 1; i <= bytes; i++) {		for (j = 0; j < 10; j++) {			d = isapnp_read_byte(0x05);			if (d & 1)				break;			udelay(10);		}		if (!(d & 1)) {			*data++ = 0xff;			continue;		}		d = isapnp_read_byte(0x04);	/* PRESDI */		isapnp_checksum_value += d;		if (data != NULL)			*data++ = d;	}}#define RDP_STEP	32	/* minimum is 4 */static int isapnp_next_rdp(void){	int rdp = isapnp_rdp;	while (rdp <= 0x3ff) {		if (!check_region(rdp, 1)) {			isapnp_rdp = rdp;			return 0;		}		rdp += RDP_STEP;	}	return -1;}/* Set read port address */static inline void isapnp_set_rdp(void){	isapnp_write_byte(0x00, isapnp_rdp >> 2);	udelay(100);}/* *	This code is badly broken. We cannot simply pick ports as the  *	ISAPnP specification implies. We should try 4 or 5 safe ports *	then bale by default. * *	This code touches NE2K cards or other devices and your box is *	history. */static int __init isapnp_isolate_rdp_select(void){	isapnp_wait();	isapnp_key();	/* Control: reset CSN and conditionally everything else too */	isapnp_write_byte(0x02, isapnp_reset ? 0x05 : 0x04);	mdelay(2);	isapnp_wait();	isapnp_key();	isapnp_wake(0x00);	if (isapnp_next_rdp() < 0) {		isapnp_wait();		return -1;	}	isapnp_set_rdp();	udelay(1000);	write_address(0x01);	udelay(1000);	return 0;}/* *  Isolate (assign uniqued CSN) to all ISA PnP devices. */static int __init isapnp_isolate(void){	unsigned char checksum = 0x6a;	unsigned char chksum = 0x00;	unsigned char bit = 0x00;	int data;	int csn = 0;	int i;	int iteration = 1;	isapnp_rdp = 0x213;	if (isapnp_isolate_rdp_select() < 0)		return -1;	while (1) {		for (i = 1; i <= 64; i++) {			data = read_data() << 8;			udelay(250);			data = data | read_data();			udelay(250);			if (data == 0x55aa)				bit = 0x01;			checksum = ((((checksum ^ (checksum >> 1)) & 0x01) ^ bit) << 7) | (checksum >> 1);			bit = 0x00;		}		for (i = 65; i <= 72; i++) {			data = read_data() << 8;			udelay(250);			data = data | read_data();			udelay(250);			if (data == 0x55aa)				chksum |= (1 << (i - 65));		}		if (checksum != 0x00 && checksum == chksum) {			csn++;			isapnp_write_byte(0x06, csn);			udelay(250);			iteration++;			isapnp_wake(0x00);			write_address(0x01);			goto __next;		}		if (iteration == 1) {			isapnp_rdp += RDP_STEP;			if (isapnp_isolate_rdp_select() < 0)				return -1;		} else if (iteration > 1) {			break;		}	      __next:		checksum = 0x6a;		chksum = 0x00;		bit = 0x00;	}	isapnp_wait();	return csn;}/* *  Read one tag from stream. */static int __init isapnp_read_tag(unsigned char *type, unsigned short *size){	unsigned char tag, tmp[2];	isapnp_peek(&tag, 1);	if (tag == 0)				/* invalid tag */		return -1;	if (tag & 0x80) {	/* large item */		*type = tag;		isapnp_peek(tmp, 2);		*size = (tmp[1] << 8) | tmp[0];	} else {		*type = (tag >> 3) & 0x0f;		*size = tag & 0x07;	}#if 0	printk("tag = 0x%x, type = 0x%x, size = %i\n", tag, *type, *size);#endif	if (type == 0)				/* wrong type */		return -1;	if (*type == 0xff && *size == 0xffff)	/* probably invalid data */		return -1;	return 0;}/* *  Skip specified number of bytes from stream. */ static void __init isapnp_skip_bytes(int count){	isapnp_peek(NULL, count);}/* *  Parse logical device tag. */static struct pnp_dev * __init isapnp_parse_device(struct pnp_bus *card,int size, int number){	unsigned char tmp[6];	struct pnp_dev *dev;	isapnp_peek(tmp, size);	dev = isapnp_alloc(sizeof(struct pnp_dev));	if (!dev)		return NULL;	dev->devfn = number;	dev->vendor = (tmp[1] << 8) | tmp[0];	dev->device = (tmp[3] << 8) | tmp[2];	dev->regs = tmp[4];	dev->bus = card;	if (size > 5)		dev->regs |= tmp[5] << 8;	dev->prepare = isapnp_config_prepare;	dev->activate = isapnp_config_activate;	dev->deactivate = isapnp_config_deactivate;	return dev;}/* *  Build new resources structure */static struct isapnp_resources * __init isapnp_build_resources(struct pnp_dev *dev, int dependent){	struct isapnp_resources *res, *ptr, *ptra;		res = isapnp_alloc(sizeof(struct isapnp_resources));	if (!res)		return NULL;	res->dev = dev;	ptr = (struct isapnp_resources *)dev->sysdata;	while (ptr && ptr->next)		ptr = ptr->next;	if (ptr && ptr->dependent && dependent) { /* add to another list */		ptra = ptr->alt;		while (ptra && ptra->alt)			ptra = ptra->alt;		if (!ptra)			ptr->alt = res;		else			ptra->alt = res;	} else {		if (!ptr)			dev->sysdata = res;		else			ptr->next = res;	}	if (dependent) {		res->priority = dependent & 0xff;		if (res->priority > ISAPNP_RES_PRIORITY_FUNCTIONAL)			res->priority = ISAPNP_RES_PRIORITY_INVALID;		res->dependent = 1;	} else {		res->priority = ISAPNP_RES_PRIORITY_PREFERRED;		res->dependent = 0;	}	return res;}/* *  Add IRQ resource to resources list. */static void __init isapnp_add_irq_resource(struct pnp_dev *dev,                                    	       struct isapnp_resources **res,                                               int dependent, int size){	unsigned char tmp[3];	struct isapnp_irq *irq, *ptr;	isapnp_peek(tmp, size);	irq = isapnp_alloc(sizeof(struct isapnp_irq));	if (!irq)		return;	if (*res == NULL) {		*res = isapnp_build_resources(dev, dependent);		if (*res == NULL) {			kfree(irq);			return;		}	}	irq->map = (tmp[1] << 8) | tmp[0];	if (size > 2)		irq->flags = tmp[2];	else		irq->flags = IORESOURCE_IRQ_HIGHEDGE;	irq->res = *res;	ptr = (*res)->irq;	while (ptr && ptr->next)		ptr = ptr->next;	if (ptr)		ptr->next = irq;	else		(*res)->irq = irq;}/* *  Add DMA resource to resources list. */static void __init isapnp_add_dma_resource(struct pnp_dev *dev,                                    	       struct isapnp_resources **res,                                    	       int dependent, int size){	unsigned char tmp[2];	struct isapnp_dma *dma, *ptr;	isapnp_peek(tmp, size);	dma = isapnp_alloc(sizeof(struct isapnp_dma));	if (!dma)		return;	if (*res == NULL) {		*res = isapnp_build_resources(dev, dependent);		if (*res == NULL) {

⌨️ 快捷键说明

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