^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * support.c - standard functions for the use of pnp protocol drivers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 2003 Adam Belay <ambx1@neo.rr.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Bjorn Helgaas <bjorn.helgaas@hp.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/pnp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "base.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * pnp_is_active - Determines if a device is active based on its current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * @dev: pointer to the desired PnP device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) int pnp_is_active(struct pnp_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * I don't think this is very reliable because pnp_disable_dev()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * only clears out auto-assigned resources.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) if (!pnp_port_start(dev, 0) && pnp_port_len(dev, 0) <= 1 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) !pnp_mem_start(dev, 0) && pnp_mem_len(dev, 0) <= 1 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) pnp_irq(dev, 0) == -1 && pnp_dma(dev, 0) == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) EXPORT_SYMBOL(pnp_is_active);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * Functionally similar to acpi_ex_eisa_id_to_string(), but that's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * buried in the ACPI CA, and we can't depend on it being present.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) void pnp_eisa_id_to_string(u32 id, char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) id = be32_to_cpu(id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * According to the specs, the first three characters are five-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * compressed ASCII, and the left-over high order bit should be zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * However, the Linux ISAPNP code historically used six bits for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * first character, and there seem to be IDs that depend on that,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * e.g., "nEC8241" in the Linux 8250_pnp serial driver and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * FreeBSD sys/pc98/cbus/sio_cbus.c driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) str[0] = 'A' + ((id >> 26) & 0x3f) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) str[1] = 'A' + ((id >> 21) & 0x1f) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) str[2] = 'A' + ((id >> 16) & 0x1f) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) str[3] = hex_asc_hi(id >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) str[4] = hex_asc_lo(id >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) str[5] = hex_asc_hi(id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) str[6] = hex_asc_lo(id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) str[7] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) char *pnp_resource_type_name(struct resource *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) switch (pnp_resource_type(res)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) case IORESOURCE_IO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return "io";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) case IORESOURCE_MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return "mem";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) case IORESOURCE_IRQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return "irq";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) case IORESOURCE_DMA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return "dma";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) case IORESOURCE_BUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return "bus";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return "unknown";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct pnp_resource *pnp_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (list_empty(&dev->resources))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) pnp_dbg(&dev->dev, "%s: no current resources\n", desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) pnp_dbg(&dev->dev, "%s: current resources:\n", desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) list_for_each_entry(pnp_res, &dev->resources, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) pnp_dbg(&dev->dev, "%pr\n", &pnp_res->res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) char *pnp_option_priority_name(struct pnp_option *option)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) switch (pnp_option_priority(option)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) case PNP_RES_PRIORITY_PREFERRED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return "preferred";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) case PNP_RES_PRIORITY_ACCEPTABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return "acceptable";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) case PNP_RES_PRIORITY_FUNCTIONAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return "functional";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return "invalid";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) void dbg_pnp_show_option(struct pnp_dev *dev, struct pnp_option *option)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) char buf[128];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) int len = 0, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct pnp_port *port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) struct pnp_mem *mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) struct pnp_irq *irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) struct pnp_dma *dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (pnp_option_is_dependent(option))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) len += scnprintf(buf + len, sizeof(buf) - len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) " dependent set %d (%s) ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) pnp_option_set(option),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) pnp_option_priority_name(option));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) len += scnprintf(buf + len, sizeof(buf) - len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) " independent ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) switch (option->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) case IORESOURCE_IO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) port = &option->u.port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) len += scnprintf(buf + len, sizeof(buf) - len, "io min %#llx "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) "max %#llx align %lld size %lld flags %#x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) (unsigned long long) port->min,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) (unsigned long long) port->max,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) (unsigned long long) port->align,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) (unsigned long long) port->size, port->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) case IORESOURCE_MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) mem = &option->u.mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) len += scnprintf(buf + len, sizeof(buf) - len, "mem min %#llx "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) "max %#llx align %lld size %lld flags %#x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) (unsigned long long) mem->min,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) (unsigned long long) mem->max,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) (unsigned long long) mem->align,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) (unsigned long long) mem->size, mem->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) case IORESOURCE_IRQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) irq = &option->u.irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) len += scnprintf(buf + len, sizeof(buf) - len, "irq");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (bitmap_empty(irq->map.bits, PNP_IRQ_NR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) len += scnprintf(buf + len, sizeof(buf) - len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) " <none>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) for (i = 0; i < PNP_IRQ_NR; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (test_bit(i, irq->map.bits))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) len += scnprintf(buf + len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) sizeof(buf) - len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) " %d", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) len += scnprintf(buf + len, sizeof(buf) - len, " flags %#x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) irq->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (irq->flags & IORESOURCE_IRQ_OPTIONAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) len += scnprintf(buf + len, sizeof(buf) - len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) " (optional)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) case IORESOURCE_DMA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) dma = &option->u.dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) len += scnprintf(buf + len, sizeof(buf) - len, "dma");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (!dma->map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) len += scnprintf(buf + len, sizeof(buf) - len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) " <none>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) for (i = 0; i < 8; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (dma->map & (1 << i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) len += scnprintf(buf + len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) sizeof(buf) - len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) " %d", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) len += scnprintf(buf + len, sizeof(buf) - len, " (bitmask %#x) "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) "flags %#x", dma->map, dma->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) pnp_dbg(&dev->dev, "%s\n", buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }