Ejemplo n.º 1
0
static void pnp_print_irq(pnp_info_buffer_t *buffer, char *space, struct pnp_irq *irq)
{
	int first = 1, i;

	pnp_printf(buffer, "%sirq ", space);
	for (i = 0; i < PNP_IRQ_NR; i++)
		if (test_bit(i, irq->map)) {
			if (!first) {
				pnp_printf(buffer, ",");
			} else {
				first = 0;
			}
			if (i == 2 || i == 9)
				pnp_printf(buffer, "2/9");
			else
				pnp_printf(buffer, "%i", i);
		}
	if (bitmap_empty(irq->map, PNP_IRQ_NR))
		pnp_printf(buffer, "<none>");
	if (irq->flags & IORESOURCE_IRQ_HIGHEDGE)
		pnp_printf(buffer, " High-Edge");
	if (irq->flags & IORESOURCE_IRQ_LOWEDGE)
		pnp_printf(buffer, " Low-Edge");
	if (irq->flags & IORESOURCE_IRQ_HIGHLEVEL)
		pnp_printf(buffer, " High-Level");
	if (irq->flags & IORESOURCE_IRQ_LOWLEVEL)
		pnp_printf(buffer, " Low-Level");
	pnp_printf(buffer, "\n");
}
Ejemplo n.º 2
0
static void pnp_print_option(pnp_info_buffer_t *buffer, char *space,
			     struct pnp_option *option, int dep)
{
	char *s;
	struct pnp_port *port;
	struct pnp_irq *irq;
	struct pnp_dma *dma;
	struct pnp_mem *mem;

	if (dep) {
		switch (option->priority) {
			case PNP_RES_PRIORITY_PREFERRED:
			s = "preferred";
			break;
			case PNP_RES_PRIORITY_ACCEPTABLE:
			s = "acceptable";
			break;
			case PNP_RES_PRIORITY_FUNCTIONAL:
			s = "functional";
			break;
			default:
			s = "invalid";
		}
		pnp_printf(buffer, "Dependent: %02i - Priority %s\n",dep, s);
	}

	for (port = option->port; port; port = port->next)
		pnp_print_port(buffer, space, port);
	for (irq = option->irq; irq; irq = irq->next)
		pnp_print_irq(buffer, space, irq);
	for (dma = option->dma; dma; dma = dma->next)
		pnp_print_dma(buffer, space, dma);
	for (mem = option->mem; mem; mem = mem->next)
		pnp_print_mem(buffer, space, mem);
}
Ejemplo n.º 3
0
static void pnp_print_dma(pnp_info_buffer_t * buffer, char *space,
			  struct pnp_dma *dma)
{
	int first = 1, i;
	char *s;

	pnp_printf(buffer, "%sdma ", space);
	for (i = 0; i < 8; i++)
		if (dma->map & (1 << i)) {
			if (!first) {
				pnp_printf(buffer, ",");
			} else {
				first = 0;
			}
			pnp_printf(buffer, "%i", i);
		}
	if (!dma->map)
		pnp_printf(buffer, "<none>");
	switch (dma->flags & IORESOURCE_DMA_TYPE_MASK) {
	case IORESOURCE_DMA_8BIT:
		s = "8-bit";
		break;
	case IORESOURCE_DMA_8AND16BIT:
		s = "8-bit&16-bit";
		break;
	default:
		s = "16-bit";
	}
	pnp_printf(buffer, " %s", s);
	if (dma->flags & IORESOURCE_DMA_MASTER)
		pnp_printf(buffer, " master");
	if (dma->flags & IORESOURCE_DMA_BYTE)
		pnp_printf(buffer, " byte-count");
	if (dma->flags & IORESOURCE_DMA_WORD)
		pnp_printf(buffer, " word-count");
	switch (dma->flags & IORESOURCE_DMA_SPEED_MASK) {
	case IORESOURCE_DMA_TYPEA:
		s = "type-A";
		break;
	case IORESOURCE_DMA_TYPEB:
		s = "type-B";
		break;
	case IORESOURCE_DMA_TYPEF:
		s = "type-F";
		break;
	default:
		s = "compatible";
		break;
	}
	pnp_printf(buffer, " %s\n", s);
}
Ejemplo n.º 4
0
static void pnp_print_mem(pnp_info_buffer_t *buffer, char *space, struct pnp_mem *mem)
{
	char *s;

	pnp_printf(buffer, "%sMemory 0x%x-0x%x, align 0x%x, size 0x%x",
			space, mem->min, mem->max, mem->align, mem->size);
	if (mem->flags & IORESOURCE_MEM_WRITEABLE)
		pnp_printf(buffer, ", writeable");
	if (mem->flags & IORESOURCE_MEM_CACHEABLE)
		pnp_printf(buffer, ", cacheable");
	if (mem->flags & IORESOURCE_MEM_RANGELENGTH)
		pnp_printf(buffer, ", range-length");
	if (mem->flags & IORESOURCE_MEM_SHADOWABLE)
		pnp_printf(buffer, ", shadowable");
	if (mem->flags & IORESOURCE_MEM_EXPANSIONROM)
		pnp_printf(buffer, ", expansion ROM");
	switch (mem->flags & IORESOURCE_MEM_TYPE_MASK) {
	case IORESOURCE_MEM_8BIT:
		s = "8-bit";
		break;
	case IORESOURCE_MEM_8AND16BIT:
		s = "8-bit&16-bit";
		break;
	case IORESOURCE_MEM_32BIT:
		s = "32-bit";
		break;
	default:
		s = "16-bit";
	}
	pnp_printf(buffer, ", %s\n", s);
}
Ejemplo n.º 5
0
static void pnp_print_port(pnp_info_buffer_t * buffer, char *space,
			   struct pnp_port *port)
{
	pnp_printf(buffer,
		   "%sport 0x%x-0x%x, align 0x%x, size 0x%x, %i-bit address decoding\n",
		   space, port->min, port->max,
		   port->align ? (port->align - 1) : 0, port->size,
		   port->flags & PNP_PORT_FLAG_16BITADDR ? 16 : 10);
}
Ejemplo n.º 6
0
static int
pnp_parse_desc(device_t dev, u_char tag, u_char *res, int len,
	       struct isa_config *config, int ldn)
{
	char buf[100];
	u_int32_t id;
	u_int32_t compat_id;
	int temp;

	id = isa_get_logicalid(dev);

	if (PNP_RES_TYPE(tag) == 0) {

		/* Small resource */
		switch (PNP_SRES_NUM(tag)) {

		case PNP_TAG_VERSION:
		case PNP_TAG_VENDOR:
			/* these descriptors are quietly ignored */
			break;

		case PNP_TAG_LOGICAL_DEVICE:
		case PNP_TAG_START_DEPENDANT:
		case PNP_TAG_END_DEPENDANT:
			if (bootverbose)
				pnp_printf(id, "unexpected small tag %d\n",
					   PNP_SRES_NUM(tag));
			/* shouldn't happen; quit now */
			return (1);

		case PNP_TAG_COMPAT_DEVICE:
			/*
			 * Got a compatible device id resource.
			 * Should keep a list of compat ids in the device.
			 */
			bcopy(res, &compat_id, 4);
			if (isa_get_compatid(dev) == 0)
				isa_set_compatid(dev, compat_id);
			break;
	    
		case PNP_TAG_IRQ_FORMAT:
			if (config->ic_nirq == ISA_NIRQ) {
				pnp_printf(id, "too many irqs\n");
				return (1);
			}
			if (I16(res) == 0) {
				/* a null descriptor */
				config->ic_irqmask[config->ic_nirq] = 0;
				config->ic_nirq++;
				break;
			}
			if (bootverbose)
				pnp_printf(id, "adding irq mask %#02x\n",
					   I16(res));
			config->ic_irqmask[config->ic_nirq] = I16(res);
			config->ic_nirq++;
			break;

		case PNP_TAG_DMA_FORMAT:
			if (config->ic_ndrq == ISA_NDRQ) {
				pnp_printf(id, "too many drqs\n");
				return (1);
			}
			if (res[0] == 0) {
				/* a null descriptor */
				config->ic_drqmask[config->ic_ndrq] = 0;
				config->ic_ndrq++;
				break;
			}
			if (bootverbose)
				pnp_printf(id, "adding dma mask %#02x\n",
					   res[0]);
			config->ic_drqmask[config->ic_ndrq] = res[0];
			config->ic_ndrq++;
			break;

		case PNP_TAG_IO_RANGE:
			if (config->ic_nport == ISA_NPORT) {
				pnp_printf(id, "too many ports\n");
				return (1);
			}
			if (res[6] == 0) {
				/* a null descriptor */
				config->ic_port[config->ic_nport].ir_start = 0;
				config->ic_port[config->ic_nport].ir_end = 0;
				config->ic_port[config->ic_nport].ir_size = 0;
				config->ic_port[config->ic_nport].ir_align = 0;
				config->ic_nport++;
				break;
			}
			if (bootverbose) {
				pnp_printf(id, "adding io range "
					   "%#x-%#x, size=%#x, "
					   "align=%#x\n",
					   I16(res + 1),
					   I16(res + 3) + res[6]-1,
					   res[6], res[5]);
			}
			config->ic_port[config->ic_nport].ir_start =
			    I16(res + 1);
			config->ic_port[config->ic_nport].ir_end =
			    I16(res + 3) + res[6] - 1;
			config->ic_port[config->ic_nport].ir_size = res[6];
			if (res[5] == 0) {
			    /* Make sure align is at least one */
			    res[5] = 1;
			}
			config->ic_port[config->ic_nport].ir_align = res[5];
			config->ic_nport++;
			pnp_check_quirks(isa_get_vendorid(dev),
					 isa_get_logicalid(dev), ldn, config);
			break;

		case PNP_TAG_IO_FIXED:
			if (config->ic_nport == ISA_NPORT) {
				pnp_printf(id, "too many ports\n");
				return (1);
			}
			if (res[2] == 0) {
				/* a null descriptor */
				config->ic_port[config->ic_nport].ir_start = 0;
				config->ic_port[config->ic_nport].ir_end = 0;
				config->ic_port[config->ic_nport].ir_size = 0;
				config->ic_port[config->ic_nport].ir_align = 0;
				config->ic_nport++;
				break;
			}
			if (bootverbose) {
				pnp_printf(id, "adding fixed io range "
					   "%#x-%#x, size=%#x, "
					   "align=%#x\n",
					   I16(res),
					   I16(res) + res[2] - 1,
					   res[2], 1);
			}
			config->ic_port[config->ic_nport].ir_start = I16(res);
			config->ic_port[config->ic_nport].ir_end =
			    I16(res) + res[2] - 1;
			config->ic_port[config->ic_nport].ir_size = res[2];
			config->ic_port[config->ic_nport].ir_align = 1;
			config->ic_nport++;
			break;

		case PNP_TAG_END:
			if (bootverbose)
				pnp_printf(id, "end config\n");
			return (1);

		default:
			/* Skip this resource */
			pnp_printf(id, "unexpected small tag %d\n",
				      PNP_SRES_NUM(tag));
			break;
		}
	} else {
		/* Large resource */
		switch (PNP_LRES_NUM(tag)) {

		case PNP_TAG_ID_UNICODE:
		case PNP_TAG_LARGE_VENDOR:
			/* these descriptors are quietly ignored */
			break;

		case PNP_TAG_ID_ANSI:
			if (len > sizeof(buf) - 1)
				len = sizeof(buf) - 1;
			bcopy(res, buf, len);

			/*
			 * Trim trailing spaces and garbage.
			 */
			while (len > 0 && buf[len - 1] <= ' ')
				len--;
			buf[len] = '\0';
			device_set_desc_copy(dev, buf);
			break;
			
		case PNP_TAG_MEMORY_RANGE:
			if (config->ic_nmem == ISA_NMEM) {
				pnp_printf(id, "too many memory ranges\n");
				return (1);
			}
			if (I16(res + 7) == 0) {
				/* a null descriptor */
				config->ic_mem[config->ic_nmem].ir_start = 0;
				config->ic_mem[config->ic_nmem].ir_end = 0;
				config->ic_mem[config->ic_nmem].ir_size = 0;
				config->ic_mem[config->ic_nmem].ir_align = 0;
				config->ic_nmem++;
				break;
			}
			if (bootverbose) {
				temp = I16(res + 7) << 8;
				pnp_printf(id, "adding memory range "
					   "%#x-%#x, size=%#x, "
					   "align=%#x\n",
					   I16(res + 1) << 8,
					   (I16(res + 3) << 8) + temp - 1,
					   temp, I16(res + 5));
			}
			config->ic_mem[config->ic_nmem].ir_start =
			    I16(res + 1) << 8;
			config->ic_mem[config->ic_nmem].ir_end =
			    (I16(res + 3) << 8) + (I16(res + 7) << 8) - 1;
			config->ic_mem[config->ic_nmem].ir_size =
			    I16(res + 7) << 8;
			config->ic_mem[config->ic_nmem].ir_align = I16(res + 5);
			if (!config->ic_mem[config->ic_nmem].ir_align)
				config->ic_mem[config->ic_nmem].ir_align =
				    0x10000;
			config->ic_nmem++;
			break;

		case PNP_TAG_MEMORY32_RANGE:
			if (config->ic_nmem == ISA_NMEM) {
				pnp_printf(id, "too many memory ranges\n");
				return (1);
			}
			if (I32(res + 13) == 0) {
				/* a null descriptor */
				config->ic_mem[config->ic_nmem].ir_start = 0;
				config->ic_mem[config->ic_nmem].ir_end = 0;
				config->ic_mem[config->ic_nmem].ir_size = 0;
				config->ic_mem[config->ic_nmem].ir_align = 0;
				config->ic_nmem++;
				break;
			}
			if (bootverbose) {
				pnp_printf(id, "adding memory32 range "
					   "%#x-%#x, size=%#x, "
					   "align=%#x\n",
					   I32(res + 1),
					   I32(res + 5) + I32(res + 13) - 1,
					   I32(res + 13), I32(res + 9));
			}
			config->ic_mem[config->ic_nmem].ir_start = I32(res + 1);
			config->ic_mem[config->ic_nmem].ir_end =
			    I32(res + 5) + I32(res + 13) - 1;
			config->ic_mem[config->ic_nmem].ir_size = I32(res + 13);
			config->ic_mem[config->ic_nmem].ir_align = I32(res + 9);
			config->ic_nmem++;
			break;

		case PNP_TAG_MEMORY32_FIXED:
			if (config->ic_nmem == ISA_NMEM) {
				pnp_printf(id, "too many memory ranges\n");
				return (1);
			}
			if (I32(res + 5) == 0) {
				/* a null descriptor */
				config->ic_mem[config->ic_nmem].ir_start = 0;
				config->ic_mem[config->ic_nmem].ir_end = 0;
				config->ic_mem[config->ic_nmem].ir_size = 0;
				config->ic_mem[config->ic_nmem].ir_align = 0;
				break;
			}
			if (bootverbose) {
				pnp_printf(id, "adding fixed memory32 range "
					   "%#x-%#x, size=%#x\n",
					   I32(res + 1),
					   I32(res + 1) + I32(res + 5) - 1,
					   I32(res + 5));
			}
			config->ic_mem[config->ic_nmem].ir_start = I32(res + 1);
			config->ic_mem[config->ic_nmem].ir_end =
			    I32(res + 1) + I32(res + 5) - 1;
			config->ic_mem[config->ic_nmem].ir_size = I32(res + 5);
			config->ic_mem[config->ic_nmem].ir_align = 1;
			config->ic_nmem++;
			break;

		default:
			/* Skip this resource */
			pnp_printf(id, "unexpected large tag %d\n",
				   PNP_SRES_NUM(tag));
			break;
		}
	}

	return (0);
}
Ejemplo n.º 7
0
void
pnp_parse_resources(device_t dev, u_char *resources, int len, int ldn)
{
	struct isa_config *configs;
	struct isa_config *config;
	device_t parent;
	int priorities[1 + MAXDEP];
	u_char *start;
	u_char *p;
	u_char tag;
	u_int32_t id;
	int ncfgs;
	int l;
	int i;

	parent = device_get_parent(dev);
	id = isa_get_logicalid(dev);

	configs = (struct isa_config *)malloc(sizeof(*configs)*(1 + MAXDEP),
					      M_DEVBUF, M_NOWAIT | M_ZERO);
	if (configs == NULL) {
		device_printf(parent, "No memory to parse PNP data\n");
		return;
	}
	config = &configs[0];
	priorities[0] = 0;
	ncfgs = 1;

	p = resources;
	start = NULL;
	while (len > 0) {
		tag = *p++;
		len--;
		if (PNP_RES_TYPE(tag) == 0) {
			/* Small resource */
			l = PNP_SRES_LEN(tag);
			if (len < l) {
				len = 0;
				continue;
			}
			len -= l;

			switch (PNP_SRES_NUM(tag)) {

			case PNP_TAG_START_DEPENDANT:
				if (start != NULL) {
					/*
					 * Copy the common resources first,
					 * then parse the "dependent" resources.
					 */
					pnp_merge_resources(dev, &configs[0],
							    config);
					pnp_parse_dependant(dev, start,
							    p - start - 1,
							    config, ldn);
				}
				start = p + l;
				if (ncfgs > MAXDEP) {
					device_printf(parent, "too many dependant configs (%d)\n", MAXDEP);
					len = 0;
					break;
				}
				config = &configs[ncfgs];
				/*
				 * If the priority is not specified,
				 * then use the default of 'acceptable'
				 */
				if (l > 0)
					priorities[ncfgs] = p[0];
				else
					priorities[ncfgs] = 1;
				if (bootverbose)
					pnp_printf(id, "start dependent (%d)\n",
						   priorities[ncfgs]);
				ncfgs++;
				break;

			case PNP_TAG_END_DEPENDANT:
				if (start == NULL) {
					device_printf(parent,
						      "malformed resources\n");
					len = 0;
					break;
				}
				/*
				 * Copy the common resources first,
				 * then parse the "dependent" resources.
				 */
				pnp_merge_resources(dev, &configs[0], config);
				pnp_parse_dependant(dev, start, p - start - 1,
						    config, ldn);
				start = NULL;
				if (bootverbose)
					pnp_printf(id, "end dependent\n");
				/*
				 * Back to the common part; clear it
				 * as its contents has already been copied
				 * to each dependant.
				 */
				config = &configs[0];
				bzero(config, sizeof(*config));
				break;

			case PNP_TAG_END:
				if (start != NULL) {
					device_printf(parent,
						      "malformed resources\n");
				}
				len = 0;
				break;

			default:
				if (start != NULL)
					/* defer parsing a dependent section */
					break;
				if (pnp_parse_desc(dev, tag, p, l, config, ldn))
					len = 0;
				break;
			}
			p += l;
		} else {
			/* Large resource */
			if (len < 2) {
				len = 0;
				break;
			}
			l = I16(p);
			p += 2;
			len -= 2;
			if (len < l) {
				len = 0;
				break;
			}
			len -= l;
			if (start == NULL &&
			    pnp_parse_desc(dev, tag, p, l, config, ldn)) {
				len = 0;
				break;
			}
			p += l;
		}
	}

	if (ncfgs == 1) {
		/* Single config without dependants */
		ISA_ADD_CONFIG(parent, dev, priorities[0], &configs[0]);
		free(configs, M_DEVBUF);
		return;
	}

	for (i = 1; i < ncfgs; i++) {
		/*
		 * Merge the remaining part of the common resources,
		 * if any. Strictly speaking, there shouldn't be common/main
		 * resources after the END_DEPENDENT tag.
		 */
		pnp_merge_resources(dev, &configs[0], &configs[i]);
		ISA_ADD_CONFIG(parent, dev, priorities[i], &configs[i]);
	}

	free(configs, M_DEVBUF);
}
Ejemplo n.º 8
0
static ssize_t pnp_show_current_resources(struct device *dmdev, struct device_attribute *attr, char *buf)
{
	struct pnp_dev *dev = to_pnp_dev(dmdev);
	int i, ret;
	pnp_info_buffer_t *buffer;

	if (!dev)
		return -EINVAL;

	buffer = (pnp_info_buffer_t *) pnp_alloc(sizeof(pnp_info_buffer_t));
	if (!buffer)
		return -ENOMEM;
	buffer->len = PAGE_SIZE;
	buffer->buffer = buf;
	buffer->curr = buffer->buffer;

	pnp_printf(buffer,"state = ");
	if (dev->active)
		pnp_printf(buffer,"active\n");
	else
		pnp_printf(buffer,"disabled\n");

	for (i = 0; i < PNP_MAX_PORT; i++) {
		if (pnp_port_valid(dev, i)) {
			pnp_printf(buffer,"io");
			if (pnp_port_flags(dev, i) & IORESOURCE_DISABLED)
				pnp_printf(buffer," disabled\n");
			else
				pnp_printf(buffer," 0x%llx-0x%llx\n",
					(unsigned long long)pnp_port_start(dev, i),
					(unsigned long long)pnp_port_end(dev, i));
		}
	}
	for (i = 0; i < PNP_MAX_MEM; i++) {
		if (pnp_mem_valid(dev, i)) {
			pnp_printf(buffer,"mem");
			if (pnp_mem_flags(dev, i) & IORESOURCE_DISABLED)
				pnp_printf(buffer," disabled\n");
			else
				pnp_printf(buffer," 0x%llx-0x%llx\n",
					(unsigned long long)pnp_mem_start(dev, i),
					(unsigned long long)pnp_mem_end(dev, i));
		}
	}
	for (i = 0; i < PNP_MAX_IRQ; i++) {
		if (pnp_irq_valid(dev, i)) {
			pnp_printf(buffer,"irq");
			if (pnp_irq_flags(dev, i) & IORESOURCE_DISABLED)
				pnp_printf(buffer," disabled\n");
			else
				pnp_printf(buffer," %lld\n",
					(unsigned long long)pnp_irq(dev, i));
		}
	}
	for (i = 0; i < PNP_MAX_DMA; i++) {
		if (pnp_dma_valid(dev, i)) {
			pnp_printf(buffer,"dma");
			if (pnp_dma_flags(dev, i) & IORESOURCE_DISABLED)
				pnp_printf(buffer," disabled\n");
			else
				pnp_printf(buffer," %lld\n",
					(unsigned long long)pnp_dma(dev, i));
		}
	}
	ret = (buffer->curr - buf);
	kfree(buffer);
	return ret;
}