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

📄 isapnp.c

📁 话带数据中传真解调程序
💻 C
📖 第 1 页 / 共 4 页
字号:
		for (dma = res->dma; dma; dma = dma->next) {			if (!index)				return dma;			index--;		}	}	return NULL;}struct isapnp_mem *isapnp_find_mem(struct pnp_dev *dev, int index){	struct isapnp_resources *res;	struct isapnp_mem *mem;		if (!dev || index < 0 || index > 7)		return NULL;	for (res = (struct isapnp_resources *)dev->sysdata; res; res = res->next) {		for (mem = res->mem; mem; mem = mem->next) {			if (!index)				return mem;			index--;		}	}	return NULL;}struct isapnp_mem32 *isapnp_find_mem32(struct pnp_dev *dev, int index){	struct isapnp_resources *res;	struct isapnp_mem32 *mem32;		if (!dev || index < 0 || index > 7)		return NULL;	for (res = (struct isapnp_resources *)dev->sysdata; res; res = res->next) {		for (mem32 = res->mem32; mem32; mem32 = mem32->next) {			if (!index)				return mem32;			index--;		}	}	return NULL;}/* *  Device manager. */struct pnp_bus *isapnp_find_card(unsigned short vendor,				 unsigned short device,				 struct pnp_bus *from){	struct pnp_bus *card;	if (from == NULL) {		from = isapnp_cards;	} else {		from = from->next;	}	for (card = from; card; card = card->next) {		if (card->vendor == vendor && card->device == device)			return card;	}	return NULL;}struct pnp_dev *isapnp_find_dev(struct pnp_bus *card,				unsigned short vendor,				unsigned short function,				struct pnp_dev *from){	struct pnp_dev *dev;	int idx;		if (card == NULL) {	/* look for a logical device from all cards */		if (from == NULL) {			from = isapnp_devices;		} else {			from = from->next;		}		for (dev = from; dev; dev = dev->next) {			if (dev->vendor == vendor && dev->device == function)				return dev;			for (idx = 0; idx < DEVICE_COUNT_COMPATIBLE; idx++)				if (dev->vendor_compatible[idx] == vendor &&				    dev->device_compatible[idx] == function)					return dev;		}	} else {		if (from == NULL) {			from = card->devices;		} else {			from = from->next;		}		if (from->bus != card)	/* something is wrong */			return NULL;		for (dev = from; dev; dev = dev->sibling) {			if (dev->vendor == vendor && dev->device == function)				return dev;			for (idx = 0; idx < DEVICE_COUNT_COMPATIBLE; idx++)				if (dev->vendor_compatible[idx] == vendor &&				    dev->device_compatible[idx] == function)					return dev;		}			}	return NULL;}static unsigned int isapnp_dma_resource_flags(struct isapnp_dma *dma){	return dma->flags | IORESOURCE_DMA | IORESOURCE_AUTO;}static unsigned int isapnp_mem_resource_flags(struct isapnp_mem *mem){	unsigned int result;	result = mem->flags | IORESOURCE_MEM | IORESOURCE_AUTO;	if (!(mem->flags & IORESOURCE_MEM_WRITEABLE))		result |= IORESOURCE_READONLY;	if (mem->flags & IORESOURCE_MEM_CACHEABLE)		result |= IORESOURCE_CACHEABLE;	if (mem->flags & IORESOURCE_MEM_RANGELENGTH)		result |= IORESOURCE_RANGELENGTH;	if (mem->flags & IORESOURCE_MEM_SHADOWABLE)		result |= IORESOURCE_SHADOWABLE;	return result;}static unsigned int isapnp_irq_resource_flags(struct isapnp_irq *irq){	return irq->flags | IORESOURCE_IRQ | IORESOURCE_AUTO;}static unsigned int isapnp_port_resource_flags(struct isapnp_port *port){	return port->flags | IORESOURCE_IO | IORESOURCE_AUTO;}static int isapnp_config_prepare(struct pnp_dev *dev){	struct isapnp_resources *res, *resa;	struct isapnp_port *port;	struct isapnp_irq *irq;	struct isapnp_dma *dma;	struct isapnp_mem *mem;	int port_count, port_count1;	int irq_count, irq_count1;	int dma_count, dma_count1;	int mem_count, mem_count1;	int idx;	if (dev == NULL)		return -EINVAL;	if (dev->active || dev->ro)		return -EBUSY;	for (idx = 0; idx < DEVICE_COUNT_IRQ; idx++) {		dev->irq_resource[idx].name = NULL;		dev->irq_resource[idx].start = 0;		dev->irq_resource[idx].end = 0;		dev->irq_resource[idx].flags = 0;	}	for (idx = 0; idx < DEVICE_COUNT_DMA; idx++) {		dev->dma_resource[idx].name = NULL;		dev->dma_resource[idx].start = 0;		dev->dma_resource[idx].end = 0;		dev->dma_resource[idx].flags = 0;	}	for (idx = 0; idx < DEVICE_COUNT_RESOURCE; idx++) {		dev->resource[idx].name = NULL;		dev->resource[idx].start = 0;		dev->resource[idx].end = 0;		dev->resource[idx].flags = 0;	}	port_count = irq_count = dma_count = mem_count = 0;	for (res = (struct isapnp_resources *)dev->sysdata; res; res = res->next) {		port_count1 = irq_count1 = dma_count1 = mem_count1 = 0;		for (resa = res; resa; resa = resa->alt) {			for (port = resa->port, idx = 0; port; port = port->next, idx++) {				if (dev->resource[port_count + idx].flags == 0) {					dev->resource[port_count + idx].flags = isapnp_port_resource_flags(port);					dev->resource[port_count + idx].end = port->size;				}			}			if (port_count1 < idx)				port_count1 = idx;			for (irq = resa->irq, idx = 0; irq; irq = irq->next, idx++) {				int count = irq_count + idx;				if (count < DEVICE_COUNT_IRQ) {					if (dev->irq_resource[count].flags == 0) {						dev->irq_resource[count].flags = isapnp_irq_resource_flags(irq);					}				}							}			if (irq_count1 < idx)				irq_count1 = idx;			for (dma = resa->dma, idx = 0; dma; dma = dma->next, idx++)				if (dev->dma_resource[idx].flags == 0) {					dev->dma_resource[idx].flags = isapnp_dma_resource_flags(dma);				}			if (dma_count1 < idx)				dma_count1 = idx;			for (mem = resa->mem, idx = 0; mem; mem = mem->next, idx++)				if (dev->resource[mem_count + idx + 8].flags == 0) {					dev->resource[mem_count + idx + 8].flags = isapnp_mem_resource_flags(mem);				}			if (mem_count1 < idx)				mem_count1 = idx;		}		port_count += port_count1;		irq_count += irq_count1;		dma_count += dma_count1;		mem_count += mem_count1;	}	return 0;}struct isapnp_cfgtmp {	struct isapnp_port *port[8];	struct isapnp_irq *irq[2];	struct isapnp_dma *dma[2];	struct isapnp_mem *mem[4];	struct pnp_dev *request;	struct pnp_dev result;};static int isapnp_alternative_switch(struct isapnp_cfgtmp *cfg,				     struct isapnp_resources *from,				     struct isapnp_resources *to){	int tmp, tmp1;	struct isapnp_port *port;	struct isapnp_irq *irq;	struct isapnp_dma *dma;	struct isapnp_mem *mem;	if (!cfg)		return -EINVAL;	/* process port settings */	for (tmp = 0; tmp < 8; tmp++) {		if (!(cfg->request->resource[tmp].flags & IORESOURCE_AUTO))			continue;		/* don't touch */		port = cfg->port[tmp];		if (!port) {			cfg->port[tmp] = port = isapnp_find_port(cfg->request, tmp);			if (!port)				return -EINVAL;		}		if (from && port->res == from) {			while (port->res != to) {				if (!port->res->alt)					return -EINVAL;				port = port->res->alt->port;				for (tmp1 = tmp; tmp1 > 0 && port; tmp1--)					port = port->next;				cfg->port[tmp] = port;				if (!port)					return -ENOENT;				cfg->result.resource[tmp].flags = isapnp_port_resource_flags(port);			}		}	}	/* process irq settings */	for (tmp = 0; tmp < 2; tmp++) {		if (!(cfg->request->irq_resource[tmp].flags & IORESOURCE_AUTO))			continue;		/* don't touch */		irq = cfg->irq[tmp];		if (!irq) {			cfg->irq[tmp] = irq = isapnp_find_irq(cfg->request, tmp);			if (!irq)				return -EINVAL;		}		if (from && irq->res == from) {			while (irq->res != to) {				if (!irq->res->alt)					return -EINVAL;				irq = irq->res->alt->irq;				for (tmp1 = tmp; tmp1 > 0 && irq; tmp1--)					irq = irq->next;				cfg->irq[tmp] = irq;				if (!irq)					return -ENOENT;				cfg->result.irq_resource[tmp].flags = isapnp_irq_resource_flags(irq);			}		}	}	/* process dma settings */	for (tmp = 0; tmp < 2; tmp++) {		if (!(cfg->request->dma_resource[tmp].flags & IORESOURCE_AUTO))			continue;		/* don't touch */		dma = cfg->dma[tmp];		if (!dma) {			cfg->dma[tmp] = dma = isapnp_find_dma(cfg->request, tmp);			if (!dma)				return -EINVAL;		}		if (from && dma->res == from) {			while (dma->res != to) {				if (!dma->res->alt)					return -EINVAL;				dma = dma->res->alt->dma;				for (tmp1 = tmp; tmp1 > 0 && dma; tmp1--)					dma = dma->next;				cfg->dma[tmp] = dma;				if (!dma)					return -ENOENT;				cfg->result.dma_resource[tmp].flags = isapnp_dma_resource_flags(dma);			}		}	}	/* process memory settings */	for (tmp = 0; tmp < 4; tmp++) {		if (!(cfg->request->resource[tmp + 8].flags & IORESOURCE_AUTO))			continue;		/* don't touch */		mem = cfg->mem[tmp];		if (!mem) {			cfg->mem[tmp] = mem = isapnp_find_mem(cfg->request, tmp);			if (!mem)				return -EINVAL;		}		if (from && mem->res == from) {			while (mem->res != to) {				if (!mem->res->alt)					return -EINVAL;				mem = mem->res->alt->mem;				for (tmp1 = tmp; tmp1 > 0 && mem; tmp1--)					mem = mem->next;				cfg->mem[tmp] = mem;				if (!mem)					return -ENOENT;				cfg->result.resource[tmp + 8].flags = isapnp_mem_resource_flags(mem);			}		}	}	return 0;}static int isapnp_check_port(struct isapnp_cfgtmp *cfg, int port, int size, int idx){	int i, tmp, rport, rsize;	struct isapnp_port *xport;	struct pnp_dev *dev;	if (check_region(port, size))		return 1;	for (i = 0; i < 8; i++) {		rport = isapnp_reserve_io[i << 1];		rsize = isapnp_reserve_io[(i << 1) + 1];		if (port >= rport && port < rport + rsize)			return 1;		if (port + size > rport && port + size < (rport + rsize) - 1)			return 1;	}	for (dev = isapnp_devices; dev; dev = dev->next) {		if (dev->active) {			for (tmp = 0; tmp < 8; tmp++) {				if (dev->resource[tmp].flags) {					rport = dev->resource[tmp].start;					rsize = (dev->resource[tmp].end - rport) + 1;					if (port >= rport && port < rport + rsize)						return 1;					if (port + size > rport && port + size < (rport + rsize) - 1)						return 1;				}			}		}	}	for (i = 0; i < 8; i++) {		unsigned int flags;		if (i == idx)			continue;		flags = cfg->request->resource[i].flags;		if (!flags)			continue;		tmp = cfg->request->resource[i].start;		if (flags & IORESOURCE_AUTO) {		/* auto */			xport = cfg->port[i];			if (!xport)				return 1;			if (cfg->result.resource[i].flags & IORESOURCE_AUTO)				continue;			tmp = cfg->result.resource[i].start;			if (tmp + xport->size >= port && tmp <= port + xport->size)				return 1;			continue;		}		if (port == tmp)			return 1;		xport = isapnp_find_port(cfg->request, i);		if (!xport)			return 1;		if (tmp + xport->size >= port && tmp <= port + xport->size)			return 1;	}	return 0;}static int isapnp_valid_port(struct isapnp_cfgtmp *cfg, int idx){	int err;	unsigned long *value1, *value2;	struct isapnp_port *port;	if (!cfg || idx < 0 || idx > 7)		return -EINVAL;	if (!(cfg->result.resource[idx].flags & IORESOURCE_AUTO)) /* don't touch */		return 0;      __again:      	port = cfg->port[idx];      	if (!port)      		return -EINVAL;      	value1 = &cfg->result.resource[idx].start;      	value2 = &cfg->result.resource[idx].end;	if (cfg->result.resource[idx].flags & IORESOURCE_AUTO) {		cfg->result.resource[idx].flags &= ~IORESOURCE_AUTO;		*value1 = port->min;		*value2 = port->min + port->size - 1;		if (!isapnp_check_port(cfg, *value1, port->size, idx))			return 0;	}	do {		*value1 += port->align;		*value2 = *value1 + port->size - 1;		if (*value1 > port->max || !port->align) {			if (port->res && port->res->alt) {				if ((err = isapnp_alternative_switch(cfg, port->res, port->res->alt))<0)					return err;				goto __again;			}			return -ENOENT;		}	} while (isapnp_check_port(cfg, *value1, port->size, idx));	return 0;}static void isapnp_test_handler(int irq, void *dev_id, struct pt_regs *regs){}static int isapnp_check_interrupt(struct isapnp_cfgtmp *cfg, int irq, int idx){	int i;	struct pnp_dev *dev;	if (irq < 0 || irq > 15)		return 1;	for (i = 0; i < 16; i++) {		if (isapnp_reserve_irq[i] == irq)			return 1;	}	for (dev = isapnp_devices; dev; dev = dev->next) {		if (dev->active) {			if (dev->irq_resource[0].start == irq ||			    dev->irq_resource[1].start == irq)				return 1;		}	}	if (request_irq(irq, isapnp_test_handler, SA_INTERRUPT, "isapnp", NULL))		return 1;	free_irq(irq, NULL);	for (i = 0; i < DEVICE_COUNT_IRQ; i++) {		if (i == idx)			continue;		if (!cfg->result.irq_resource[i].flags)			continue;		if (cfg->result.irq_resource[i].flags & IORESOURCE_AUTO)			continue;		if (cfg->result.irq_resource[i].start == irq)			return 1;	}	return 0;}static int isapnp_valid_irq(struct isapnp_cfgtmp *cfg, int idx){	/* IRQ priority: this table is good for i386 */	static unsigned short xtab[16] = {		5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2	};	int err, i;	unsigned long *value1, *value2;	struct isapnp_irq *irq;	if (!cfg || idx < 0 || idx > 1)		return -EINVAL;	if (!(cfg->result.irq_resource[idx].flags & IORESOURCE_AUTO))		return 0;      __again:      	irq = cfg->irq[idx];      	if (!irq)      		return -EINVAL;      	value1 = &cfg->result.irq_resource[idx].start;      	value2 = &cfg->result.irq_resource[idx].end;	if (cfg->result.irq_resource[idx].flags & IORESOURCE_AUTO) {		for (i = 0; i < 16 && !(irq->map & (1<<xtab[i])); i++);		if (i >= 16)			return -ENOENT;		cfg->result.irq_resource[idx].flags &= ~IORESOURCE_AUTO;		if (!isapnp_check_interrupt(cfg, *value1 = *value2 = xtab[i], idx))			return 0;	}	do {		for (i = 0; i < 16 && xtab[i] != *value1; i++);		for (i++; i < 16 && !(irq->map & (1<<xtab[i])); i++);		if (i >= 16) {			if (irq->res && irq->res->alt) {				if ((err = isapnp_alternative_switch(cfg, irq->res, irq->res->alt))<0)					return err;				goto __again;			}			return -ENOENT;		} else {			*value1 = *value2 = xtab[i];		}	} while (isapnp_check_interrupt(cfg, *value1, idx));	return 0;}static int isapnp_check_dma(struct isapnp_cfgtmp *cfg, int dma, int idx){	int i;	struct pnp_dev *dev;	if (dma < 0 || dma == 4 || dma > 7)		return 1;	for (i = 0; i < 8; i++) {		if (isapnp_reserve_dma[i] == dma)			return 1;	}	for (dev = isapnp_devices; dev; dev = dev->next) {		if (dev->active) {			if (dev->dma_resource[0].start == dma || dev->dma_resource[1].start == dma)				return 1;		}	}	if (request_dma(dma, "isapnp"))		return 1;	free_dma(dma);	for (i = 0; i < 2; i++) {		if (i == idx)			continue;		if (!cfg->result.dma_resource[i].flags ||		    (cfg->result.dma_resource[i].flags & IORESOURCE_AUTO))			continue;		if (cfg->result.dma_resource[i].start == dma)			return 1;	}	return 0;}static int isapnp_valid_dma(struct isapnp_cfgtmp *cfg, int idx){	int err, i;

⌨️ 快捷键说明

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