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

📄 isapnp.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	/* 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 pci_dev *dev;	/* Some machines allow DMA 0, but others don't. In fact on some 	   boxes DMA 0 is the memory refresh. Play safe */	   	if (dma < 1 || dma == 4 || dma > 7)		return 1;	for (i = 0; i < 8; i++) {		if (isapnp_reserve_dma[i] == dma)			return 1;	}	isapnp_for_each_dev(dev) {		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;	unsigned long *value1, *value2;	struct isapnp_dma *dma;	if (!cfg || idx < 0 || idx > 1)		return -EINVAL;	if (!(cfg->result.dma_resource[idx].flags & IORESOURCE_AUTO))	/* don't touch */		return 0;      __again:      	dma = cfg->dma[idx];      	if (!dma)      		return -EINVAL;      	value1 = &cfg->result.dma_resource[idx].start;      	value2 = &cfg->result.dma_resource[idx].end;	if (cfg->result.dma_resource[idx].flags & IORESOURCE_AUTO) {		for (i = 0; i < 8 && !(dma->map & (1<<i)); i++);		if (i >= 8)			return -ENOENT;		cfg->result.dma_resource[idx].flags &= ~IORESOURCE_AUTO;		if (!isapnp_check_dma(cfg, *value1 = *value2 = i, idx))			return 0;	}	do {		for (i = *value1 + 1; i < 8 && !(dma->map & (1<<i)); i++);		if (i >= 8) {			if (dma->res && dma->res->alt) {				if ((err = isapnp_alternative_switch(cfg, dma->res, dma->res->alt))<0)					return err;				goto __again;			}			return -ENOENT;		} else {			*value1 = *value2 = i;		}	} while (isapnp_check_dma(cfg, *value1, idx));	return 0;}static int isapnp_check_mem(struct isapnp_cfgtmp *cfg, unsigned int addr, unsigned int size, int idx){	int i, tmp;	unsigned int raddr, rsize;	struct isapnp_mem *xmem;	struct pci_dev *dev;	for (i = 0; i < 8; i++) {		raddr = (unsigned int)isapnp_reserve_mem[i << 1];		rsize = (unsigned int)isapnp_reserve_mem[(i << 1) + 1];		if (addr >= raddr && addr < raddr + rsize)			return 1;		if (addr + size > raddr && addr + size < (raddr + rsize) - 1)			return 1;		if (__check_region(&iomem_resource, addr, size))			return 1;	}	isapnp_for_each_dev(dev) {		if (dev->active) {			for (tmp = 0; tmp < 4; tmp++) {				if (dev->resource[tmp].flags) {					raddr = dev->resource[tmp + 8].start;					rsize = (dev->resource[tmp + 8].end - raddr) + 1;					if (addr >= raddr && addr < raddr + rsize)						return 1;					if (addr + size > raddr && addr + size < (raddr + rsize) - 1)						return 1;				}			}		}	}	for (i = 0; i < 4; i++) {		unsigned int flags = cfg->request->resource[i + 8].flags;		if (i == idx)			continue;		if (!flags)			continue;		tmp = cfg->result.resource[i + 8].start;		if (flags & IORESOURCE_AUTO) {		/* auto */			xmem = cfg->mem[i];			if (!xmem)				return 1;			if (cfg->result.resource[i + 8].flags & IORESOURCE_AUTO)				continue;			if (tmp + xmem->size >= addr && tmp <= addr + xmem->size)				return 1;			continue;		}		if (addr == tmp)			return 1;		xmem = isapnp_find_mem(cfg->request, i);		if (!xmem)			return 1;		if (tmp + xmem->size >= addr && tmp <= addr + xmem->size)			return 1;	}	return 0;}static int isapnp_valid_mem(struct isapnp_cfgtmp *cfg, int idx){	int err;	unsigned long *value1, *value2;	struct isapnp_mem *mem;	if (!cfg || idx < 0 || idx > 3)		return -EINVAL;	if (!(cfg->result.resource[idx + 8].flags & IORESOURCE_AUTO)) /* don't touch */		return 0;      __again:      	mem = cfg->mem[idx];      	if (!mem)      		return -EINVAL;      	value1 = &cfg->result.resource[idx + 8].start;      	value2 = &cfg->result.resource[idx + 8].end;	if (cfg->result.resource[idx + 8].flags & IORESOURCE_AUTO) {		cfg->result.resource[idx + 8].flags &= ~IORESOURCE_AUTO;		*value1 = mem->min;		*value2 = mem->min + mem->size - 1;		if (!isapnp_check_mem(cfg, *value1, mem->size, idx))			return 0;	}	do {		*value1 += mem->align;		*value2 = *value1 + mem->size - 1;		if (*value1 > mem->max || !mem->align) {			if (mem->res && mem->res->alt) {				if ((err = isapnp_alternative_switch(cfg, mem->res, mem->res->alt))<0)					return err;				goto __again;			}			return -ENOENT;		}	} while (isapnp_check_mem(cfg, *value1, mem->size, idx));	return 0;}static int isapnp_check_valid(struct isapnp_cfgtmp *cfg){	int tmp;		for (tmp = 0; tmp < 8; tmp++)		if (cfg->result.resource[tmp].flags & IORESOURCE_AUTO)			return -EAGAIN;	for (tmp = 0; tmp < 2; tmp++)		if (cfg->result.irq_resource[tmp].flags & IORESOURCE_AUTO)			return -EAGAIN;	for (tmp = 0; tmp < 2; tmp++)		if (cfg->result.dma_resource[tmp].flags & IORESOURCE_AUTO)			return -EAGAIN;	for (tmp = 0; tmp < 4; tmp++)		if (cfg->result.resource[tmp + 8].flags & IORESOURCE_AUTO)			return -EAGAIN;	return 0;}static int isapnp_config_activate(struct pci_dev *dev){	struct isapnp_cfgtmp cfg;	int tmp, fauto, err;		if (!dev)		return -EINVAL;	if (dev->active)		return -EBUSY;	memset(&cfg, 0, sizeof(cfg));	cfg.request = dev;	memcpy(&cfg.result, dev, sizeof(struct pci_dev));	/* check if all values are set, otherwise try auto-configuration */	for (tmp = fauto = 0; !fauto && tmp < 8; tmp++) {		if (dev->resource[tmp].flags & IORESOURCE_AUTO)			fauto++;	}	for (tmp = 0; !fauto && tmp < 2; tmp++) {		if (dev->irq_resource[tmp].flags & IORESOURCE_AUTO)			fauto++;	}	for (tmp = 0; !fauto && tmp < 2; tmp++) {		if (dev->dma_resource[tmp].flags & IORESOURCE_AUTO)			fauto++;	}	for (tmp = 0; !fauto && tmp < 4; tmp++) {		if (dev->resource[tmp + 8].flags & IORESOURCE_AUTO)			fauto++;	}	if (!fauto)		goto __skip_auto;	/* set variables to initial values */	if ((err = isapnp_alternative_switch(&cfg, NULL, NULL))<0)		return err;	/* find first valid configuration */	fauto = 0;	do {		for (tmp = 0; tmp < 8 && cfg.result.resource[tmp].flags; tmp++)			if ((err = isapnp_valid_port(&cfg, tmp))<0)				return err;		for (tmp = 0; tmp < 2 && cfg.result.irq_resource[tmp].flags; tmp++)			if ((err = isapnp_valid_irq(&cfg, tmp))<0)				return err;		for (tmp = 0; tmp < 2 && cfg.result.dma_resource[tmp].flags; tmp++)			if ((err = isapnp_valid_dma(&cfg, tmp))<0)				return err;		for (tmp = 0; tmp < 4 && cfg.result.resource[tmp + 8].flags; tmp++)			if ((err = isapnp_valid_mem(&cfg, tmp))<0)				return err;	} while (isapnp_check_valid(&cfg)<0 && fauto++ < 20);	if (fauto >= 20)		return -EAGAIN;      __skip_auto:      	/* we have valid configuration, try configure hardware */      	isapnp_cfg_begin(dev->bus->number, dev->devfn);	dev->active = 1;	dev->irq_resource[0] = cfg.result.irq_resource[0];	dev->irq_resource[1] = cfg.result.irq_resource[1];	dev->dma_resource[0] = cfg.result.dma_resource[0];	dev->dma_resource[1] = cfg.result.dma_resource[1];	for (tmp = 0; tmp < 12; tmp++) {		dev->resource[tmp] = cfg.result.resource[tmp];	}		for (tmp = 0; tmp < 8 && dev->resource[tmp].flags; tmp++)		isapnp_write_word(ISAPNP_CFG_PORT+(tmp<<1), dev->resource[tmp].start);	for (tmp = 0; tmp < 2 && dev->irq_resource[tmp].flags; tmp++) {		int irq = dev->irq_resource[tmp].start;		if (irq == 2)			irq = 9;		isapnp_write_byte(ISAPNP_CFG_IRQ+(tmp<<1), irq);	}	for (tmp = 0; tmp < 2 && dev->dma_resource[tmp].flags; tmp++)		isapnp_write_byte(ISAPNP_CFG_DMA+tmp, dev->dma_resource[tmp].start);	for (tmp = 0; tmp < 4 && dev->resource[tmp+8].flags; tmp++)		isapnp_write_word(ISAPNP_CFG_MEM+(tmp<<2), (dev->resource[tmp + 8].start >> 8) & 0xffff);	isapnp_activate(dev->devfn);	isapnp_cfg_end();	return 0;}static int isapnp_config_deactivate(struct pci_dev *dev){	if (!dev || !dev->active)		return -EINVAL;      	isapnp_cfg_begin(dev->bus->number, dev->devfn);	isapnp_deactivate(dev->devfn);	dev->active = 0;	isapnp_cfg_end();	return 0;}void isapnp_resource_change(struct resource *resource,			    unsigned long start,			    unsigned long size){	if (resource == NULL)		return;	resource->flags &= ~IORESOURCE_AUTO;	resource->start = start;	resource->end = start + size - 1;}/* *  Inititialization. */#ifdef MODULEstatic void isapnp_free_port(struct isapnp_port *port){	struct isapnp_port *next;	while (port) {		next = port->next;		kfree(port);		port = next;	}}static void isapnp_free_irq(struct isapnp_irq *irq){	struct isapnp_irq *next;	while (irq) {		next = irq->next;		kfree(irq);		irq = next;	}}static void isapnp_free_dma(struct isapnp_dma *dma){	struct isapnp_dma *next;	while (dma) {		next = dma->next;		kfree(dma);		dma = next;	}}static void isapnp_free_mem(struct isapnp_mem *mem){	struct isapnp_mem *next;	while (mem) {		next = mem->next;		kfree(mem);		mem = next;	}}static void isapnp_free_mem32(struct isapnp_mem32 *mem32){	struct isapnp_mem32 *next;	while (mem32) {		next = mem32->next;		kfree(mem32);		mem32 = next;	}}static void isapnp_free_resources(struct isapnp_resources *resources, int alt){	struct isapnp_resources *next;	while (resources) {		next = alt ? resources->alt : resources->next;		isapnp_free_port(resources->port);		isapnp_free_irq(resources->irq);		isapnp_free_dma(resources->dma);		isapnp_free_mem(resources->mem);		isapnp_free_mem32(resources->mem32);		if (!alt && resources->alt)			isapnp_free_resources(resources->alt, 1);		kfree(resources);		resources = next;	}}static void isapnp_free_card(struct pci_bus *card){	while (!list_empty(&card->devices)) {		struct list_head *list = card->devices.next;		struct pci_dev *dev = pci_dev_b(list);		list_del(list);		isapnp_free_resources((struct isapnp_resources *)dev->sysdata, 0);		kfree(dev);	}	kfree(card);}#endif /* MODULE */static void isapnp_free_all_resources(void){#ifdef ISAPNP_REGION_OK	if (pidxr_res)		release_resource(pidxr_res);#endif	if (pnpwrp_res)		release_resource(pnpwrp_res);	if (isapnp_rdp >= 0x203 && isapnp_rdp <= 0x3ff && isapnp_rdp_res)		release_resource(isapnp_rdp_res);#ifdef MODULE#ifdef CONFIG_PROC_FS	isapnp_proc_done();#endif	while (!list_empty(&isapnp_cards)) {		struct list_head *list = isapnp_cards.next;		list_del(list);		isapnp_free_card(pci_bus_b(list));	}#endif}EXPORT_SYMBOL(isapnp_cards);EXPORT_SYMBOL(isapnp_devices);EXPORT_SYMBOL(isapnp_present);EXPORT_SYMBOL(isapnp_cfg_begin);EXPORT_SYMBOL(isapnp_cfg_end);EXPORT_SYMBOL(isapnp_read_byte);EXPORT_SYMBOL(isapnp_read_word);EXPORT_SYMBOL(isapnp_read_dword);EXPORT_SYMBOL(isapnp_write_byte);EXPORT_SYMBOL(isapnp_write_word);EXPORT_SYMBOL(isapnp_write_dword);EXPORT_SYMBOL(isapnp_wake);EXPORT_SYMBOL(isapnp_device);EXPORT_SYMBOL(isapnp_activate);EXPORT_SYMBOL(isapnp_deactivate);EXPORT_SYMBOL(isapnp_find_card);EXPORT_SYMBOL(isapnp_find_dev);EXPORT_SYMBOL(isapnp_probe_cards);EXPORT_SYMBOL(isapnp_probe_devs);EXPORT_SYMBOL(isapnp_activate_dev);EXPORT_SYMBOL(isapnp_resource_change);int __init isapnp_init(void){	int cards;	struct pci_bus *card;	if (isapnp_disable) {		isapnp_detected = 0;		printk("isapnp: ISA Plug & Play support disabled\n");		return 0;	}#ifdef ISAPNP_REGION_OK	pidxr_res=request_region(_PIDXR, 1, "isapnp index");	if(!pidxr_res) {		printk("isapnp: Index Register 0x%x already used\n", _PIDXR);		return -EBUSY;	}#endif	pnpwrp_res=request_region(_PNPWRP, 1, "isapnp write");	if(!pnpwrp_res) {		printk("isapnp: Write Data Register 0x%x already used\n", _PNPWRP);		return -EBUSY;	}		/*	 *	Print a message. The existing ISAPnP code is hanging machines	 *	so let the user know where.	 */	 	printk("isapnp: Scanning for Pnp cards...\n");	if (isapnp_rdp >= 0x203 && isapnp_rdp <= 0x3ff) {		isapnp_rdp |= 3;		isapnp_rdp_res=request_region(isapnp_rdp, 1, "isapnp read");		if(!isapnp_rdp_res) {			printk("isapnp: Read Data Register 0x%x already used\n", isapnp_rdp);			return -EBUSY;		}		isapnp_set_rdp();	}	isapnp_detected = 1;	if (isapnp_rdp < 0x203 || isapnp_rdp > 0x3ff) {		cards = isapnp_isolate();		if (cards < 0 || 		    (isapnp_rdp < 0x203 || isapnp_rdp > 0x3ff)) {			isapnp_free_all_resources();			isapnp_detected = 0;			printk("isapnp: No Plug & Play device found\n");			return 0;		}		isapnp_rdp_res=request_region(isapnp_rdp, 1, "isapnp read");	}	isapnp_build_device_list();	cards = 0;	isapnp_for_each_card(card) {		cards++;		if (isapnp_verbose) {			struct list_head *devlist;			printk( "isapnp: Card '%s'\n", card->name[0]?card->name:"Unknown");			if (isapnp_verbose < 2)				continue;			for (devlist = card->devices.next; devlist != &card->devices; devlist = devlist->next) {				struct pci_dev *dev = pci_dev_b(devlist);				printk("isapnp:   Device '%s'\n", dev->name[0]?card->name:"Unknown");			}		}	}	if (cards) {		printk("isapnp: %i Plug & Play card%s detected total\n", cards, cards>1?"s":"");	} else {		printk("isapnp: No Plug & Play card found\n");	}#ifdef CONFIG_PROC_FS	isapnp_proc_init();#endif	return 0;}#ifdef MODULEint init_module(void){	return isapnp_init();}void cleanup_module(void){	if (isapnp_detected)		isapnp_free_all_resources();}#endif

⌨️ 快捷键说明

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