acpi_enum.c revision 8e56767d5805b843712c67bce2d732cc722f154b
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* ACPI enumerator
*/
#include "acpi.h"
extern void free_master_data();
extern void process_master_file();
extern int master_file_lookup(char *, char **, char **, char **);
extern int master_file_lookups(char *, char **, char **, char **, int);
static char keyboard_alias[] = "keyboard";
static char mouse_alias[] = "mouse";
#define ACPI_ENUM_DEBUG "acpi_enum_debug"
#define PARSE_RESOURCES_DEBUG 0x0001
#define MASTER_LOOKUP_DEBUG 0x0002
#define DEVICES_NOT_ENUMED 0x0004
#define PARSE_RES_IRQ 0x0008
#define PARSE_RES_DMA 0x0010
#define PARSE_RES_MEMORY 0x0020
#define PARSE_RES_IO 0x0040
#define PARSE_RES_ADDRESS 0x0080
#define ISA_DEVICE_ENUM 0x1000
#define PROCESS_CIDS 0x2000
static unsigned long acpi_enum_debug = 0x00;
static char USED_RESOURCES[] = "used-resources";
static unsigned short used_interrupts = 0;
static unsigned short used_dmas = 0;
typedef struct used_io_mem {
unsigned int start_addr;
unsigned int length;
struct used_io_mem *next;
static int used_io_count = 0;
static int used_mem_count = 0;
#define MAX_PARSED_ACPI_RESOURCES 255
#define ACPI_ISA_LIMIT 16
#define ACPI_ELEMENT_PACKAGE_LIMIT 32
#define EISA_ID_SIZE 7
/*
*/
static void
{
(*used_count)++;
return;
}
/* find a place to insert */
}
/* head */
return;
} else {
}
}
static void
{
int i;
for (i = 0; i < io_count; i++) {
KM_SLEEP);
&used_io_head);
} else {
}
}
}
static void
{
int i;
for (i = 0; i < irq.NumberOfInterrupts; i++) {
interrupt[(*interrupt_count)++] =
irq.Interrupts[i];
if (acpi_enum_debug & PARSE_RES_IRQ) {
"IRQ num %u, intr # = %u",
i, irq.Interrupts[i]);
}
}
}
static void
{
int i;
for (i = 0; i < acpi_dma.NumberOfChannels; i++) {
if (acpi_enum_debug & PARSE_RES_DMA) {
"DMA num %u, channel # = %u",
}
}
}
static void
int *io_count)
{
/* When Min equals Max, IO is 32-bit */
} else {
/* else IO is 10-bit ISA */
"!ACPI source type ACPI_RSTYPE_IO"\
"10-bit ISA range not supported");
}
if (acpi_enum_debug & PARSE_RES_IO) {
"IO min 0x%X, max 0x%X, length: 0x%X",
}
(*io_count)++;
}
static void
int *io_count)
{
if (acpi_enum_debug & PARSE_RES_IO) {
"Fixed IO 0x%X, length: 0x%X",
}
(*io_count)++;
}
static void
int *io_count)
{
if (acpi_enum_debug & PARSE_RES_MEMORY) {
"Fixed Mem 32 %ul, length: %ul",
}
(*io_count)++;
}
static void
int *io_count)
{
(*io_count)++;
if (acpi_enum_debug & PARSE_RES_MEMORY) {
"Mem 32 0x%X, length: 0x%X",
}
return;
}
if (acpi_enum_debug & PARSE_RES_MEMORY) {
"MEM32 Min Max not equal!");
"Mem 32 MinBaseAddress 0x%X, MaxBaseAddress: 0x%X",
}
}
static void
int *io_count)
{
if (acpi_enum_debug & PARSE_RES_ADDRESS) {
"ADDRESS 16 MEMORY RANGE");
} else
"ADDRESS 16 IO RANGE");
} else {
"ADDRESS 16 OTHER");
}
"%s "\
"MinAddressFixed 0x%X, "\
"MaxAddressFixed 0x%X, "\
"MinAddressRange 0x%X, "\
"MaxAddressRange 0x%X, "\
"length: 0x%X\n",
"CONSUMER" : "PRODUCER",
}
return;
}
if (addr16.AddressLength > 0) {
/* memory */
} else {
/* io */
}
(*io_count)++;
}
}
static void
int *io_count)
{
if (acpi_enum_debug & PARSE_RES_ADDRESS) {
"ADDRESS 32 MEMORY RANGE");
} else
"ADDRESS 32 IO RANGE");
} else {
"ADDRESS 32 OTHER");
}
"%s "\
"MinAddressFixed 0x%X, "\
"MaxAddressFixed 0x%X, "\
"MinAddressRange 0x%X, "\
"MaxAddressRange 0x%X, "\
"length: 0x%X\n",
"CONSUMER" : "PRODUCER",
}
return;
}
if (addr32.AddressLength > 0) {
/* memory */
} else {
/* io */
}
(*io_count)++;
}
}
static void
int *io_count)
{
if (acpi_enum_debug & PARSE_RES_ADDRESS) {
"ADDRESS 64 MEMORY RANGE");
} else
"ADDRESS 64 IO RANGE");
} else {
"ADDRESS 64 OTHER");
}
#ifdef _LP64
"%s "\
"MinAddressFixed 0x%X, "\
"MaxAddressFixed 0x%X, "\
"MinAddressRange 0x%lX, "\
"MaxAddressRange 0x%lX, "\
"length: 0x%lX\n",
#else
"%s "\
"MinAddressFixed 0x%X, "\
"MaxAddressFixed 0x%X, "\
"MinAddressRange 0x%llX, "\
"MaxAddressRange 0x%llX, "\
"length: 0x%llX\n",
#endif
"CONSUMER" : "PRODUCER",
}
return;
}
if (addr64.AddressLength > 0) {
/* memory */
} else {
/* io */
}
(*io_count)++;
}
}
static ACPI_STATUS
{
char *current_ptr, *last_ptr;
int i;
return (status);
}
while (current_ptr < last_ptr) {
if (io_count >= MAX_PARSED_ACPI_RESOURCES) {
break;
}
switch (resource_ptr->Id) {
case ACPI_RSTYPE_END_TAG:
break;
case ACPI_RSTYPE_IO:
break;
case ACPI_RSTYPE_FIXED_IO:
break;
case ACPI_RSTYPE_FIXED_MEM32:
&io_count);
break;
case ACPI_RSTYPE_MEM32:
break;
case ACPI_RSTYPE_ADDRESS16:
break;
case ACPI_RSTYPE_ADDRESS32:
break;
case ACPI_RSTYPE_ADDRESS64:
break;
case ACPI_RSTYPE_IRQ:
break;
case ACPI_RSTYPE_DMA:
break;
case ACPI_RSTYPE_START_DPF:
"!ACPI source type ACPI_RSTYPE_START_DPF not "\
"supported");
break;
case ACPI_RSTYPE_END_DPF:
"!ACPI source type ACPI_RSTYPE_END_DPF not "\
"supported");
break;
case ACPI_RSTYPE_VENDOR:
"!ACPI source type ACPI_RSTYPE_VENDOR not "\
"supported");
break;
case ACPI_RSTYPE_MEM24:
"!ACPI source type ACPI_RSTYPE_MEM24 not "\
"supported");
break;
case ACPI_RSTYPE_EXT_IRQ:
"!ACPI source type ACPI_RSTYPE_EXT_IRQ not "\
"supported");
break;
default:
/* Some types are not yet implemented (See CA 6.4) */
"!ACPI resource type (0X%X) not yet supported",
resource_ptr->Id);
break;
}
}
if (io_count) {
/*
* on LX50, you get interrupts of mouse and keyboard
* from separate PNP id...
*/
if (io_count == 2) {
interrupt[0] = 0x1;
interrupt_count = 2;
1 << interrupt[0];
}
}
}
}
}
}
return (status);
}
/* keyboard mouse is under i8042, everything else under isa */
static dev_info_t *
{
struct regspec i8042_regs[] = {
{1, 0x60, 0x1},
{1, 0x64, 0x1}
};
return (isa_dip);
if (i8042_dip)
return (i8042_dip);
&i8042_dip);
"unit-address", "1,60");
(void) ndi_devi_bind_driver(i8042_dip, 0);
return (i8042_dip);
}
/*
* put content of properties (if any) to dev info tree at branch xdip
*
*/
static void
{
if (properties == NULL) {
return; /* nothing to add */
}
return; /* don't know how to process this */
}
*tmp = '\0';
tmp++;
if (*tmp == '"') {
tmp++;
}
*tmp = '\0';
}
/* put back original value to avoid kmem corruption */
*org1 = '=';
}
*tmp = '"';
}
}
void
{
static const char hextab[] = "0123456789ABCDEF";
/*
* Expand an EISA device name:
*
* This is the inverse of the above routine. It converts a 32-bit EISA
* device "id" to a 7-byte ASCII device name, which is stored at "np".
*/
*np = 0;
}
/*
* process_cids() -- process multiple CIDs in a package
*/
static void
{
char *tmp_cidstr;
int i;
*cidstr_size = 0;
return; /* empty package */
}
/* figure out the total cid size needed */
/* total up all CIDs size */
case ACPI_TYPE_INTEGER:
break;
case ACPI_TYPE_STRING:
break;
default:
break;
}
}
tmp_cidstr = *cidstr;
/* get the actual acpi_object */
case ACPI_TYPE_INTEGER:
if (acpi_enum_debug & PROCESS_CIDS) {
}
break;
case ACPI_TYPE_STRING:
if (acpi_enum_debug & PROCESS_CIDS) {
}
break;
default:
if (acpi_enum_debug & PROCESS_CIDS) {
}
break;
}
}
if (acpi_enum_debug & PROCESS_CIDS) {
}
}
/*
* isa_acpi_callback()
*/
static ACPI_STATUS
void **b)
{
int cidstr_size = 0;
char *description = NULL;
char *properties = NULL;
/*
* get full ACPI pathname for object
*/
goto done;
}
/*
* Get device info object
*/
" info for %s", path);
goto done;
}
/*
* If device isn't present, we don't enumerate
* NEEDSWORK: what about docking bays and the like?
*/
/*
* CA 6.3.6 _STA method
* Bit 0 -- device is present
* Bit 1 -- device is enabled
* Bit 2 -- device is shown in UI
*/
goto done;
}
} else {
goto done;
}
/*
* Keep track of _HID value
*/
/* No _HID, we skip this node */
goto done;
}
/*
* Attempt to get _CID value
*/
case ACPI_TYPE_INTEGER:
cidstr_size = 8;
break;
case ACPI_TYPE_STRING:
break;
case ACPI_TYPE_PACKAGE:
break;
default:
break;
}
}
/*
* Note carefully: expressions are evaluated left to right, so
* this first checks for _HID and then for _CID match
*/
cidstr_size)) {
/* PNP description found in master table */
dip = ddi_root_node();
} else {
}
"compatible", hidstr);
"model", description);
} else {
/* for ISA devices not known to the master file */
/* a keyboard device includes PNP03xx */
"compatible", "pnpPNP,303");
"model", "PNP03xx keyboard");
} else {
/* a mouse device include PNP0Fxx */
(void) ndi_prop_update_string(DDI_DEV_T_NONE,
(void) ndi_prop_update_string(DDI_DEV_T_NONE,
} else {
if (acpi_enum_debug & DEVICES_NOT_ENUMED) {
"Not enum HID(%s), CID(%s)\n",
}
goto done;
}
}
}
if (acpi_enum_debug & MASTER_LOOKUP_DEBUG) {
}
path);
if (cidstr) {
char *cids[ACPI_ELEMENT_PACKAGE_LIMIT];
char *t = cidstr;
int i = 0;
while (t < (cidstr + cidstr_size)) {
if (*t == NULL) {
t++;
continue;
}
cids[i++] = t;
t += strlen(t);
}
"_CID", (char **)cids, i);
}
/* Special processing for mouse and keyboard devices per IEEE 1275 */
/* if master entry doesn't contain "compatible" then we add default */
"device-type", keyboard_alias);
"compatible", "pnpPNP,303");
}
"device-type", mouse_alias);
"compatible", "pnpPNP,f03");
}
}
(void) ndi_devi_bind_driver(xdip, 0);
done:
if (description != NULL)
if (properties != NULL)
return (AE_OK);
}
static void
used_res_interrupts(void)
{
int intr[ACPI_ISA_LIMIT];
int count = 0;
int i;
for (i = 0; i < ACPI_ISA_LIMIT; i++) {
if ((used_interrupts >> i) & 1) {
}
}
}
static void
used_res_dmas(void)
{
int dma[ACPI_ISA_LIMIT];
int count = 0;
int i;
for (i = 0; i < ACPI_ISA_LIMIT; i++) {
if ((used_dmas >> i) & 1) {
}
}
}
static void
{
int *io;
int i;
*count *= 2;
for (i = 0; i < *count; i += 2) {
}
}
}
/*
* acpi_isa_device_enum() -- call from isa nexus driver
* returns 1 if deviced enumeration is successful
* 0 if deviced enumeration fails
*/
int
{
char *acpi_prop;
long data;
acpi_enum_debug = (unsigned long)data;
}
}
if (acpi_enum_debug & ISA_DEVICE_ENUM) {
#ifdef _LP64
#else
#endif
}
if (acpica_init() != AE_OK) {
/* Note, pickup by i8042 nexus */
return (0);
}
}
/*
* Do the actual enumeration
*/
(void) ndi_devi_bind_driver(usedrdip, 0);
return (1);
}