drivers/pnp/quirks.c

Source file repositories/reference/linux-study-clean/drivers/pnp/quirks.c

File Facts

System
Linux kernel
Corpus path
drivers/pnp/quirks.c
Extension
.c
Size
12190 bytes
Lines
454
Domain
Driver Families
Bucket
drivers/pnp
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

pnp_option_set(option) != set) {
			set = pnp_option_set(option);
			quirk_awe32_add_ports(dev, option, 0x800);
			quirk_awe32_add_ports(dev, option, 0x400);
		}
	}
}

static void quirk_cmi8330_resources(struct pnp_dev *dev)
{
	struct pnp_option *option;
	struct pnp_irq *irq;
	struct pnp_dma *dma;

	list_for_each_entry(option, &dev->options, list) {
		if (!pnp_option_is_dependent(option))
			continue;

		if (option->type == IORESOURCE_IRQ) {
			irq = &option->u.irq;
			bitmap_zero(irq->map.bits, PNP_IRQ_NR);
			__set_bit(5, irq->map.bits);
			__set_bit(7, irq->map.bits);
			__set_bit(10, irq->map.bits);
			dev_info(&dev->dev, "set possible IRQs in "
				 "option set %d to 5, 7, 10\n",
				 pnp_option_set(option));
		} else if (option->type == IORESOURCE_DMA) {
			dma = &option->u.dma;
			if ((dma->flags & IORESOURCE_DMA_TYPE_MASK) ==
						IORESOURCE_DMA_8BIT &&
			    dma->map != 0x0A) {
				dev_info(&dev->dev, "changing possible "
					 "DMA channel mask in option set %d "
					 "from %#02x to 0x0A (1, 3)\n",
					 pnp_option_set(option), dma->map);
				dma->map = 0x0A;
			}
		}
	}
}

static void quirk_sb16audio_resources(struct pnp_dev *dev)
{
	struct pnp_option *option;
	unsigned int prev_option_flags = ~0, n = 0;
	struct pnp_port *port;

	/*
	 * The default range on the OPL port for these devices is 0x388-0x388.
	 * Here we increase that range so that two such cards can be
	 * auto-configured.
	 */
	list_for_each_entry(option, &dev->options, list) {
		if (prev_option_flags != option->flags) {
			prev_option_flags = option->flags;
			n = 0;
		}

		if (pnp_option_is_dependent(option) &&
		    option->type == IORESOURCE_IO) {
			n++;
			port = &option->u.port;
			if (n == 3 && port->min == port->max) {
				port->max += 0x70;
				dev_info(&dev->dev, "increased option port "
					 "range from %#llx-%#llx to "
					 "%#llx-%#llx\n",
					 (unsigned long long) port->min,
					 (unsigned long long) port->min,
					 (unsigned long long) port->min,
					 (unsigned long long) port->max);
			}
		}
	}
}

static struct pnp_option *pnp_clone_dependent_set(struct pnp_dev *dev,
						  unsigned int set)
{
	struct pnp_option *tail = NULL, *first_new_option = NULL;
	struct pnp_option *option, *new_option;
	unsigned int flags;

	list_for_each_entry(option, &dev->options, list) {
		if (pnp_option_is_dependent(option))
			tail = option;
	}
	if (!tail) {
		dev_err(&dev->dev, "no dependent option sets\n");

Annotation

Implementation Notes