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

📄 core.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  Add 32-bit fixed memory resource to resources list. */static void __init isapnp_parse_fixed_mem32_resource(struct pnp_option *option,						       int size){	unsigned char tmp[9];	struct pnp_mem *mem;	isapnp_peek(tmp, size);	mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);	if (!mem)		return;	mem->min = mem->max = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1];	mem->size = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5];	mem->align = 0;	mem->flags = tmp[0];	pnp_register_mem_resource(option,mem);}/* *  Parse card name for ISA PnP device. */ static void __initisapnp_parse_name(char *name, unsigned int name_max, unsigned short *size){	if (name[0] == '\0') {		unsigned short size1 = *size >= name_max ? (name_max - 1) : *size;		isapnp_peek(name, size1);		name[size1] = '\0';		*size -= size1;		/* clean whitespace from end of string */		while (size1 > 0  &&  name[--size1] == ' ')			name[size1] = '\0';	}}/* *  Parse resource map for logical device. */static int __init isapnp_create_device(struct pnp_card *card,				       unsigned short size){	int number = 0, skip = 0, priority = 0, compat = 0;	unsigned char type, tmp[17];	struct pnp_option *option;	struct pnp_dev *dev;	if ((dev = isapnp_parse_device(card, size, number++)) == NULL)		return 1;	option = pnp_register_independent_option(dev);	if (!option) {		kfree(dev);		return 1;	}	pnp_add_card_device(card,dev);	while (1) {		if (isapnp_read_tag(&type, &size)<0)			return 1;		if (skip && type != _STAG_LOGDEVID && type != _STAG_END)			goto __skip;		switch (type) {		case _STAG_LOGDEVID:			if (size >= 5 && size <= 6) {				if ((dev = isapnp_parse_device(card, size, number++)) == NULL)					return 1;				size = 0;				skip = 0;				option = pnp_register_independent_option(dev);				if (!option)					return 1;				pnp_add_card_device(card,dev);			} else {				skip = 1;			}			priority = 0;			compat = 0;			break;		case _STAG_COMPATDEVID:			if (size == 4 && compat < DEVICE_COUNT_COMPATIBLE) {				isapnp_peek(tmp, 4);				isapnp_parse_id(dev,(tmp[1] << 8) | tmp[0], (tmp[3] << 8) | tmp[2]);				compat++;				size = 0;			}			break;		case _STAG_IRQ:			if (size < 2 || size > 3)				goto __skip;			isapnp_parse_irq_resource(option, size);			size = 0;			break;		case _STAG_DMA:			if (size != 2)				goto __skip;			isapnp_parse_dma_resource(option, size);			size = 0;			break;		case _STAG_STARTDEP:			if (size > 1)				goto __skip;			priority = 0x100 | PNP_RES_PRIORITY_ACCEPTABLE;			if (size > 0) {				isapnp_peek(tmp, size);				priority = 0x100 | tmp[0];				size = 0;			}			option = pnp_register_dependent_option(dev,priority);			if (!option)				return 1;			break;		case _STAG_ENDDEP:			if (size != 0)				goto __skip;			priority = 0;			break;		case _STAG_IOPORT:			if (size != 7)				goto __skip;			isapnp_parse_port_resource(option, size);			size = 0;			break;		case _STAG_FIXEDIO:			if (size != 3)				goto __skip;			isapnp_parse_fixed_port_resource(option, size);			size = 0;			break;		case _STAG_VENDOR:			break;		case _LTAG_MEMRANGE:			if (size != 9)				goto __skip;			isapnp_parse_mem_resource(option, size);			size = 0;			break;		case _LTAG_ANSISTR:			isapnp_parse_name(dev->name, sizeof(dev->name), &size);			break;		case _LTAG_UNICODESTR:			/* silently ignore */			/* who use unicode for hardware identification? */			break;		case _LTAG_VENDOR:			break;		case _LTAG_MEM32RANGE:			if (size != 17)				goto __skip;			isapnp_parse_mem32_resource(option, size);			size = 0;			break;		case _LTAG_FIXEDMEM32RANGE:			if (size != 9)				goto __skip;			isapnp_parse_fixed_mem32_resource(option, size);			size = 0;			break;		case _STAG_END:			if (size > 0)				isapnp_skip_bytes(size);			return 1;		default:			printk(KERN_ERR "isapnp: unexpected or unknown tag type 0x%x for logical device %i (device %i), ignored\n", type, dev->number, card->number);		}	      __skip:	      	if (size > 0)		      	isapnp_skip_bytes(size);	}	return 0;}/* *  Parse resource map for ISA PnP card. */static void __init isapnp_parse_resource_map(struct pnp_card *card){	unsigned char type, tmp[17];	unsigned short size;	while (1) {		if (isapnp_read_tag(&type, &size)<0)			return;		switch (type) {		case _STAG_PNPVERNO:			if (size != 2)				goto __skip;			isapnp_peek(tmp, 2);			card->pnpver = tmp[0];			card->productver = tmp[1];			size = 0;			break;		case _STAG_LOGDEVID:			if (size >= 5 && size <= 6) {				if (isapnp_create_device(card, size)==1)					return;				size = 0;			}			break;		case _STAG_VENDOR:			break;		case _LTAG_ANSISTR:			isapnp_parse_name(card->name, sizeof(card->name), &size);			break;		case _LTAG_UNICODESTR:			/* silently ignore */			/* who use unicode for hardware identification? */			break;		case _LTAG_VENDOR:			break;		case _STAG_END:			if (size > 0)				isapnp_skip_bytes(size);			return;		default:			printk(KERN_ERR "isapnp: unexpected or unknown tag type 0x%x for device %i, ignored\n", type, card->number);		}	      __skip:	      	if (size > 0)		      	isapnp_skip_bytes(size);	}}/* *  Compute ISA PnP checksum for first eight bytes. */static unsigned char __init isapnp_checksum(unsigned char *data){	int i, j;	unsigned char checksum = 0x6a, bit, b;	for (i = 0; i < 8; i++) {		b = data[i];		for (j = 0; j < 8; j++) {			bit = 0;			if (b & (1 << j))				bit = 1;			checksum = ((((checksum ^ (checksum >> 1)) & 0x01) ^ bit) << 7) | (checksum >> 1);		}	}	return checksum;}/* *  Parse EISA id for ISA PnP card. */static void isapnp_parse_card_id(struct pnp_card * card, unsigned short vendor, unsigned short device){	struct pnp_id * id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);	if (!id)		return;	sprintf(id->id, "%c%c%c%x%x%x%x",			'A' + ((vendor >> 2) & 0x3f) - 1,			'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1,			'A' + ((vendor >> 8) & 0x1f) - 1,			(device >> 4) & 0x0f,			device & 0x0f,			(device >> 12) & 0x0f,			(device >> 8) & 0x0f);	pnp_add_card_id(id,card);}/* *  Build device list for all present ISA PnP devices. */static int __init isapnp_build_device_list(void){	int csn;	unsigned char header[9], checksum;	struct pnp_card *card;	isapnp_wait();	isapnp_key();	for (csn = 1; csn <= isapnp_csn_count; csn++) {		isapnp_wake(csn);		isapnp_peek(header, 9);		checksum = isapnp_checksum(header);#if 0		printk(KERN_DEBUG "vendor: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",			header[0], header[1], header[2], header[3],			header[4], header[5], header[6], header[7], header[8]);		printk(KERN_DEBUG "checksum = 0x%x\n", checksum);#endif		if ((card = kcalloc(1, sizeof(struct pnp_card), GFP_KERNEL)) == NULL)			continue;		card->number = csn;		INIT_LIST_HEAD(&card->devices);		isapnp_parse_card_id(card, (header[1] << 8) | header[0], (header[3] << 8) | header[2]);		card->serial = (header[7] << 24) | (header[6] << 16) | (header[5] << 8) | header[4];		isapnp_checksum_value = 0x00;		isapnp_parse_resource_map(card);		if (isapnp_checksum_value != 0x00)			printk(KERN_ERR "isapnp: checksum for device %i is not valid (0x%x)\n", csn, isapnp_checksum_value);		card->checksum = isapnp_checksum_value;		card->protocol = &isapnp_protocol;		pnp_add_card(card);	}	isapnp_wait();	return 0;}/* *  Basic configuration routines. */int isapnp_present(void){	struct pnp_card *card;	pnp_for_each_card(card) {		if (card->protocol == &isapnp_protocol)			return 1;	}	return 0;}int isapnp_cfg_begin(int csn, int logdev){	if (csn < 1 || csn > isapnp_csn_count || logdev > 10)		return -EINVAL;	down(&isapnp_cfg_mutex);	isapnp_wait();	isapnp_key();	isapnp_wake(csn);#if 0	/* to avoid malfunction when the isapnptools package is used */	/* we must set RDP to our value again */	/* it is possible to set RDP only in the isolation phase */	/*   Jens Thoms Toerring <Jens.Toerring@physik.fu-berlin.de> */	isapnp_write_byte(0x02, 0x04);	/* clear CSN of card */	mdelay(2);			/* is this necessary? */	isapnp_wake(csn);		/* bring card into sleep state */	isapnp_wake(0);			/* bring card into isolation state */	isapnp_set_rdp();		/* reset the RDP port */	udelay(1000);			/* delay 1000us */	isapnp_write_byte(0x06, csn);	/* reset CSN to previous value */	udelay(250);			/* is this necessary? */#endif	if (logdev >= 0)		isapnp_device(logdev);	return 0;}int isapnp_cfg_end(void){	isapnp_wait();	up(&isapnp_cfg_mutex);	return 0;}/* *  Inititialization. */EXPORT_SYMBOL(isapnp_protocol);EXPORT_SYMBOL(isapnp_present);EXPORT_SYMBOL(isapnp_cfg_begin);EXPORT_SYMBOL(isapnp_cfg_end);#if 0EXPORT_SYMBOL(isapnp_read_byte);#endifEXPORT_SYMBOL(isapnp_write_byte);static int isapnp_read_resources(struct pnp_dev *dev, struct pnp_resource_table *res){	int tmp, ret;	dev->active = isapnp_read_byte(ISAPNP_CFG_ACTIVATE);	if (dev->active) {		for (tmp = 0; tmp < PNP_MAX_PORT; tmp++) {			ret = isapnp_read_word(ISAPNP_CFG_PORT + (tmp << 1));			if (!ret)				continue;			res->port_resource[tmp].start = ret;			res->port_resource[tmp].flags = IORESOURCE_IO;		}		for (tmp = 0; tmp < PNP_MAX_MEM; tmp++) {			ret = isapnp_read_word(ISAPNP_CFG_MEM + (tmp << 3)) << 8;			if (!ret)				continue;			res->mem_resource[tmp].start = ret;			res->mem_resource[tmp].flags = IORESOURCE_MEM;		}		for (tmp = 0; tmp < PNP_MAX_IRQ; tmp++) {			ret = (isapnp_read_word(ISAPNP_CFG_IRQ + (tmp << 1)) >> 8);			if (!ret)				continue;			res->irq_resource[tmp].start = res->irq_resource[tmp].end = ret;			res->irq_resource[tmp].flags = IORESOURCE_IRQ;		}		for (tmp = 0; tmp < PNP_MAX_DMA; tmp++) {			ret = isapnp_read_byte(ISAPNP_CFG_DMA + tmp);			if (ret == 4)				continue;			res->dma_resource[tmp].start = res->dma_resource[tmp].end = ret;			res->dma_resource[tmp].flags = IORESOURCE_DMA;		}	}	return 0;}static int isapnp_get_resources(struct pnp_dev *dev, struct pnp_resource_table * res){	int ret;	pnp_init_resource_table(res);	isapnp_cfg_begin(dev->card->number, dev->number);	ret = isapnp_read_resources(dev, res);	isapnp_cfg_end();	return ret;}static int isapnp_set_resources(struct pnp_dev *dev, struct pnp_resource_table * res){	int tmp;	isapnp_cfg_begin(dev->card->number, dev->number);	dev->active = 1;	for (tmp = 0; tmp < PNP_MAX_PORT && (res->port_resource[tmp].flags & (IORESOURCE_IO | IORESOURCE_UNSET)) == IORESOURCE_IO; tmp++)		isapnp_write_word(ISAPNP_CFG_PORT+(tmp<<1), res->port_resource[tmp].start);	for (tmp = 0; tmp < PNP_MAX_IRQ && (res->irq_resource[tmp].flags & (IORESOURCE_IRQ | IORESOURCE_UNSET)) == IORESOURCE_IRQ; tmp++) {		int irq = res->irq_resource[tmp].start;		if (irq == 2)			irq = 9;		isapnp_write_byte(ISAPNP_CFG_IRQ+(tmp<<1), irq);	}	for (tmp = 0; tmp < PNP_MAX_DMA && (res->dma_resource[tmp].flags & (IORESOURCE_DMA | IORESOURCE_UNSET)) == IORESOURCE_DMA; tmp++)		isapnp_write_byte(ISAPNP_CFG_DMA+tmp, res->dma_resource[tmp].start);	for (tmp = 0; tmp < PNP_MAX_MEM && (res->mem_resource[tmp].flags & (IORESOURCE_MEM | IORESOURCE_UNSET)) == IORESOURCE_MEM; tmp++)		isapnp_write_word(ISAPNP_CFG_MEM+(tmp<<3), (res->mem_resource[tmp].start >> 8) & 0xffff);	/* FIXME: We aren't handling 32bit mems properly here */	isapnp_activate(dev->number);	isapnp_cfg_end();	return 0;}static int isapnp_disable_resources(struct pnp_dev *dev){	if (!dev || !dev->active)		return -EINVAL;	isapnp_cfg_begin(dev->card->number, dev->number);	isapnp_deactivate(dev->number);	dev->active = 0;	isapnp_cfg_end();	return 0;}struct pnp_protocol isapnp_protocol = {	.name	= "ISA Plug and Play",	.get	= isapnp_get_resources,	.set	= isapnp_set_resources,	.disable = isapnp_disable_resources,};static int __init isapnp_init(void){	int cards;	struct pnp_card *card;	struct pnp_dev *dev;	if (isapnp_disable) {		isapnp_detected = 0;		printk(KERN_INFO "isapnp: ISA Plug & Play support disabled\n");		return 0;	}#ifdef ISAPNP_REGION_OK	if (!request_region(_PIDXR, 1, "isapnp index")) {		printk(KERN_ERR "isapnp: Index Register 0x%x already used\n", _PIDXR);		return -EBUSY;	}#endif	if (!request_region(_PNPWRP, 1, "isapnp write")) {		printk(KERN_ERR "isapnp: Write Data Register 0x%x already used\n", _PNPWRP);#ifdef ISAPNP_REGION_OK		release_region(_PIDXR, 1);#endif		return -EBUSY;	}	if(pnp_register_protocol(&isapnp_protocol)<0)		return -EBUSY;	/*	 *	Print a message. The existing ISAPnP code is hanging machines	 *	so let the user know where.	 */	 	printk(KERN_INFO "isapnp: Scanning for PnP cards...\n");	if (isapnp_rdp >= 0x203 && isapnp_rdp <= 0x3ff) {		isapnp_rdp |= 3;		if (!request_region(isapnp_rdp, 1, "isapnp read")) {			printk(KERN_ERR "isapnp: Read Data Register 0x%x already used\n", isapnp_rdp);#ifdef ISAPNP_REGION_OK			release_region(_PIDXR, 1);#endif			release_region(_PNPWRP, 1);			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)) {#ifdef ISAPNP_REGION_OK			release_region(_PIDXR, 1);#endif			release_region(_PNPWRP, 1);			isapnp_detected = 0;			printk(KERN_INFO "isapnp: No Plug & Play device found\n");			return 0;		}		request_region(isapnp_rdp, 1, "isapnp read");	}	isapnp_build_device_list();	cards = 0;	protocol_for_each_card(&isapnp_protocol,card) {		cards++;		if (isapnp_verbose) {			printk(KERN_INFO "isapnp: Card '%s'\n", card->name[0]?card->name:"Unknown");			if (isapnp_verbose < 2)				continue;			card_for_each_dev(card,dev) {				printk(KERN_INFO "isapnp:   Device '%s'\n", dev->name[0]?dev->name:"Unknown");			}		}	}	if (cards) {		printk(KERN_INFO "isapnp: %i Plug & Play card%s detected total\n", cards, cards>1?"s":"");	} else {		printk(KERN_INFO "isapnp: No Plug & Play card found\n");	}	isapnp_proc_init();	return 0;}device_initcall(isapnp_init);/* format is: noisapnp */static int __init isapnp_setup_disable(char *str){	isapnp_disable = 1;	return 1;}__setup("noisapnp", isapnp_setup_disable);/* format is: isapnp=rdp,reset,skip_pci_scan,verbose */static int __init isapnp_setup_isapnp(char *str){	(void)((get_option(&str,&isapnp_rdp) == 2) &&	       (get_option(&str,&isapnp_reset) == 2) &&	       (get_option(&str,&isapnp_verbose) == 2));	return 1;}__setup("isapnp=", isapnp_setup_isapnp);

⌨️ 快捷键说明

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