Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6595 serge 1
/******************************************************************************
2
 *
3
 * Module Name: utids - support for device Ids - HID, UID, CID, SUB, CLS
4
 *
5
 *****************************************************************************/
6
 
7
/*
8
 * Copyright (C) 2000 - 2015, Intel Corp.
9
 * All rights reserved.
10
 *
11
 * Redistribution and use in source and binary forms, with or without
12
 * modification, are permitted provided that the following conditions
13
 * are met:
14
 * 1. Redistributions of source code must retain the above copyright
15
 *    notice, this list of conditions, and the following disclaimer,
16
 *    without modification.
17
 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18
 *    substantially similar to the "NO WARRANTY" disclaimer below
19
 *    ("Disclaimer") and any redistribution must be conditioned upon
20
 *    including a substantially similar Disclaimer requirement for further
21
 *    binary redistribution.
22
 * 3. Neither the names of the above-listed copyright holders nor the names
23
 *    of any contributors may be used to endorse or promote products derived
24
 *    from this software without specific prior written permission.
25
 *
26
 * Alternatively, this software may be distributed under the terms of the
27
 * GNU General Public License ("GPL") version 2 as published by the Free
28
 * Software Foundation.
29
 *
30
 * NO WARRANTY
31
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35
 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41
 * POSSIBILITY OF SUCH DAMAGES.
42
 */
43
 
44
#include 
45
#include "accommon.h"
46
#include "acinterp.h"
47
 
48
#define _COMPONENT          ACPI_UTILITIES
49
ACPI_MODULE_NAME("utids")
50
 
51
/*******************************************************************************
52
 *
53
 * FUNCTION:    acpi_ut_execute_HID
54
 *
55
 * PARAMETERS:  device_node         - Node for the device
56
 *              return_id           - Where the string HID is returned
57
 *
58
 * RETURN:      Status
59
 *
60
 * DESCRIPTION: Executes the _HID control method that returns the hardware
61
 *              ID of the device. The HID is either an 32-bit encoded EISAID
62
 *              Integer or a String. A string is always returned. An EISAID
63
 *              is converted to a string.
64
 *
65
 *              NOTE: Internal function, no parameter validation
66
 *
67
 ******************************************************************************/
68
acpi_status
69
acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
70
		    struct acpi_pnp_device_id **return_id)
71
{
72
	union acpi_operand_object *obj_desc;
73
	struct acpi_pnp_device_id *hid;
74
	u32 length;
75
	acpi_status status;
76
 
77
	ACPI_FUNCTION_TRACE(ut_execute_HID);
78
 
79
	status = acpi_ut_evaluate_object(device_node, METHOD_NAME__HID,
80
					 ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING,
81
					 &obj_desc);
82
	if (ACPI_FAILURE(status)) {
83
		return_ACPI_STATUS(status);
84
	}
85
 
86
	/* Get the size of the String to be returned, includes null terminator */
87
 
88
	if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
89
		length = ACPI_EISAID_STRING_SIZE;
90
	} else {
91
		length = obj_desc->string.length + 1;
92
	}
93
 
94
	/* Allocate a buffer for the HID */
95
 
96
	hid =
97
	    ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) +
98
				 (acpi_size) length);
99
	if (!hid) {
100
		status = AE_NO_MEMORY;
101
		goto cleanup;
102
	}
103
 
104
	/* Area for the string starts after PNP_DEVICE_ID struct */
105
 
106
	hid->string =
107
	    ACPI_ADD_PTR(char, hid, sizeof(struct acpi_pnp_device_id));
108
 
109
	/* Convert EISAID to a string or simply copy existing string */
110
 
111
	if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
112
		acpi_ex_eisa_id_to_string(hid->string, obj_desc->integer.value);
113
	} else {
114
		strcpy(hid->string, obj_desc->string.pointer);
115
	}
116
 
117
	hid->length = length;
118
	*return_id = hid;
119
 
120
cleanup:
121
 
122
	/* On exit, we must delete the return object */
123
 
124
	acpi_ut_remove_reference(obj_desc);
125
	return_ACPI_STATUS(status);
126
}
127
 
128
/*******************************************************************************
129
 *
130
 * FUNCTION:    acpi_ut_execute_SUB
131
 *
132
 * PARAMETERS:  device_node         - Node for the device
133
 *              return_id           - Where the _SUB is returned
134
 *
135
 * RETURN:      Status
136
 *
137
 * DESCRIPTION: Executes the _SUB control method that returns the subsystem
138
 *              ID of the device. The _SUB value is always a string containing
139
 *              either a valid PNP or ACPI ID.
140
 *
141
 *              NOTE: Internal function, no parameter validation
142
 *
143
 ******************************************************************************/
144
 
145
acpi_status
146
acpi_ut_execute_SUB(struct acpi_namespace_node *device_node,
147
		    struct acpi_pnp_device_id **return_id)
148
{
149
	union acpi_operand_object *obj_desc;
150
	struct acpi_pnp_device_id *sub;
151
	u32 length;
152
	acpi_status status;
153
 
154
	ACPI_FUNCTION_TRACE(ut_execute_SUB);
155
 
156
	status = acpi_ut_evaluate_object(device_node, METHOD_NAME__SUB,
157
					 ACPI_BTYPE_STRING, &obj_desc);
158
	if (ACPI_FAILURE(status)) {
159
		return_ACPI_STATUS(status);
160
	}
161
 
162
	/* Get the size of the String to be returned, includes null terminator */
163
 
164
	length = obj_desc->string.length + 1;
165
 
166
	/* Allocate a buffer for the SUB */
167
 
168
	sub =
169
	    ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) +
170
				 (acpi_size) length);
171
	if (!sub) {
172
		status = AE_NO_MEMORY;
173
		goto cleanup;
174
	}
175
 
176
	/* Area for the string starts after PNP_DEVICE_ID struct */
177
 
178
	sub->string =
179
	    ACPI_ADD_PTR(char, sub, sizeof(struct acpi_pnp_device_id));
180
 
181
	/* Simply copy existing string */
182
 
183
	strcpy(sub->string, obj_desc->string.pointer);
184
	sub->length = length;
185
	*return_id = sub;
186
 
187
cleanup:
188
 
189
	/* On exit, we must delete the return object */
190
 
191
	acpi_ut_remove_reference(obj_desc);
192
	return_ACPI_STATUS(status);
193
}
194
 
195
/*******************************************************************************
196
 *
197
 * FUNCTION:    acpi_ut_execute_UID
198
 *
199
 * PARAMETERS:  device_node         - Node for the device
200
 *              return_id           - Where the string UID is returned
201
 *
202
 * RETURN:      Status
203
 *
204
 * DESCRIPTION: Executes the _UID control method that returns the unique
205
 *              ID of the device. The UID is either a 64-bit Integer (NOT an
206
 *              EISAID) or a string. Always returns a string. A 64-bit integer
207
 *              is converted to a decimal string.
208
 *
209
 *              NOTE: Internal function, no parameter validation
210
 *
211
 ******************************************************************************/
212
 
213
acpi_status
214
acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
215
		    struct acpi_pnp_device_id **return_id)
216
{
217
	union acpi_operand_object *obj_desc;
218
	struct acpi_pnp_device_id *uid;
219
	u32 length;
220
	acpi_status status;
221
 
222
	ACPI_FUNCTION_TRACE(ut_execute_UID);
223
 
224
	status = acpi_ut_evaluate_object(device_node, METHOD_NAME__UID,
225
					 ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING,
226
					 &obj_desc);
227
	if (ACPI_FAILURE(status)) {
228
		return_ACPI_STATUS(status);
229
	}
230
 
231
	/* Get the size of the String to be returned, includes null terminator */
232
 
233
	if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
234
		length = ACPI_MAX64_DECIMAL_DIGITS + 1;
235
	} else {
236
		length = obj_desc->string.length + 1;
237
	}
238
 
239
	/* Allocate a buffer for the UID */
240
 
241
	uid =
242
	    ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) +
243
				 (acpi_size) length);
244
	if (!uid) {
245
		status = AE_NO_MEMORY;
246
		goto cleanup;
247
	}
248
 
249
	/* Area for the string starts after PNP_DEVICE_ID struct */
250
 
251
	uid->string =
252
	    ACPI_ADD_PTR(char, uid, sizeof(struct acpi_pnp_device_id));
253
 
254
	/* Convert an Integer to string, or just copy an existing string */
255
 
256
	if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
257
		acpi_ex_integer_to_string(uid->string, obj_desc->integer.value);
258
	} else {
259
		strcpy(uid->string, obj_desc->string.pointer);
260
	}
261
 
262
	uid->length = length;
263
	*return_id = uid;
264
 
265
cleanup:
266
 
267
	/* On exit, we must delete the return object */
268
 
269
	acpi_ut_remove_reference(obj_desc);
270
	return_ACPI_STATUS(status);
271
}
272
 
273
/*******************************************************************************
274
 *
275
 * FUNCTION:    acpi_ut_execute_CID
276
 *
277
 * PARAMETERS:  device_node         - Node for the device
278
 *              return_cid_list     - Where the CID list is returned
279
 *
280
 * RETURN:      Status, list of CID strings
281
 *
282
 * DESCRIPTION: Executes the _CID control method that returns one or more
283
 *              compatible hardware IDs for the device.
284
 *
285
 *              NOTE: Internal function, no parameter validation
286
 *
287
 * A _CID method can return either a single compatible ID or a package of
288
 * compatible IDs. Each compatible ID can be one of the following:
289
 * 1) Integer (32 bit compressed EISA ID) or
290
 * 2) String (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss")
291
 *
292
 * The Integer CIDs are converted to string format by this function.
293
 *
294
 ******************************************************************************/
295
 
296
acpi_status
297
acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
298
		    struct acpi_pnp_device_id_list **return_cid_list)
299
{
300
	union acpi_operand_object **cid_objects;
301
	union acpi_operand_object *obj_desc;
302
	struct acpi_pnp_device_id_list *cid_list;
303
	char *next_id_string;
304
	u32 string_area_size;
305
	u32 length;
306
	u32 cid_list_size;
307
	acpi_status status;
308
	u32 count;
309
	u32 i;
310
 
311
	ACPI_FUNCTION_TRACE(ut_execute_CID);
312
 
313
	/* Evaluate the _CID method for this device */
314
 
315
	status = acpi_ut_evaluate_object(device_node, METHOD_NAME__CID,
316
					 ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING
317
					 | ACPI_BTYPE_PACKAGE, &obj_desc);
318
	if (ACPI_FAILURE(status)) {
319
		return_ACPI_STATUS(status);
320
	}
321
 
322
	/*
323
	 * Get the count and size of the returned _CIDs. _CID can return either
324
	 * a Package of Integers/Strings or a single Integer or String.
325
	 * Note: This section also validates that all CID elements are of the
326
	 * correct type (Integer or String).
327
	 */
328
	if (obj_desc->common.type == ACPI_TYPE_PACKAGE) {
329
		count = obj_desc->package.count;
330
		cid_objects = obj_desc->package.elements;
331
	} else {		/* Single Integer or String CID */
332
 
333
		count = 1;
334
		cid_objects = &obj_desc;
335
	}
336
 
337
	string_area_size = 0;
338
	for (i = 0; i < count; i++) {
339
 
340
		/* String lengths include null terminator */
341
 
342
		switch (cid_objects[i]->common.type) {
343
		case ACPI_TYPE_INTEGER:
344
 
345
			string_area_size += ACPI_EISAID_STRING_SIZE;
346
			break;
347
 
348
		case ACPI_TYPE_STRING:
349
 
350
			string_area_size += cid_objects[i]->string.length + 1;
351
			break;
352
 
353
		default:
354
 
355
			status = AE_TYPE;
356
			goto cleanup;
357
		}
358
	}
359
 
360
	/*
361
	 * Now that we know the length of the CIDs, allocate return buffer:
362
	 * 1) Size of the base structure +
363
	 * 2) Size of the CID PNP_DEVICE_ID array +
364
	 * 3) Size of the actual CID strings
365
	 */
366
	cid_list_size = sizeof(struct acpi_pnp_device_id_list) +
367
	    ((count - 1) * sizeof(struct acpi_pnp_device_id)) +
368
	    string_area_size;
369
 
370
	cid_list = ACPI_ALLOCATE_ZEROED(cid_list_size);
371
	if (!cid_list) {
372
		status = AE_NO_MEMORY;
373
		goto cleanup;
374
	}
375
 
376
	/* Area for CID strings starts after the CID PNP_DEVICE_ID array */
377
 
378
	next_id_string = ACPI_CAST_PTR(char, cid_list->ids) +
379
	    ((acpi_size) count * sizeof(struct acpi_pnp_device_id));
380
 
381
	/* Copy/convert the CIDs to the return buffer */
382
 
383
	for (i = 0; i < count; i++) {
384
		if (cid_objects[i]->common.type == ACPI_TYPE_INTEGER) {
385
 
386
			/* Convert the Integer (EISAID) CID to a string */
387
 
388
			acpi_ex_eisa_id_to_string(next_id_string,
389
						  cid_objects[i]->integer.
390
						  value);
391
			length = ACPI_EISAID_STRING_SIZE;
392
		} else {	/* ACPI_TYPE_STRING */
393
 
394
			/* Copy the String CID from the returned object */
395
 
396
			strcpy(next_id_string, cid_objects[i]->string.pointer);
397
			length = cid_objects[i]->string.length + 1;
398
		}
399
 
400
		cid_list->ids[i].string = next_id_string;
401
		cid_list->ids[i].length = length;
402
		next_id_string += length;
403
	}
404
 
405
	/* Finish the CID list */
406
 
407
	cid_list->count = count;
408
	cid_list->list_size = cid_list_size;
409
	*return_cid_list = cid_list;
410
 
411
cleanup:
412
 
413
	/* On exit, we must delete the _CID return object */
414
 
415
	acpi_ut_remove_reference(obj_desc);
416
	return_ACPI_STATUS(status);
417
}
418
 
419
/*******************************************************************************
420
 *
421
 * FUNCTION:    acpi_ut_execute_CLS
422
 *
423
 * PARAMETERS:  device_node         - Node for the device
424
 *              return_id           - Where the _CLS is returned
425
 *
426
 * RETURN:      Status
427
 *
428
 * DESCRIPTION: Executes the _CLS control method that returns PCI-defined
429
 *              class code of the device. The _CLS value is always a package
430
 *              containing PCI class information as a list of integers.
431
 *              The returned string has format "BBSSPP", where:
432
 *                BB = Base-class code
433
 *                SS = Sub-class code
434
 *                PP = Programming Interface code
435
 *
436
 ******************************************************************************/
437
 
438
acpi_status
439
acpi_ut_execute_CLS(struct acpi_namespace_node *device_node,
440
		    struct acpi_pnp_device_id **return_id)
441
{
442
	union acpi_operand_object *obj_desc;
443
	union acpi_operand_object **cls_objects;
444
	u32 count;
445
	struct acpi_pnp_device_id *cls;
446
	u32 length;
447
	acpi_status status;
448
	u8 class_code[3] = { 0, 0, 0 };
449
 
450
	ACPI_FUNCTION_TRACE(ut_execute_CLS);
451
 
452
	status = acpi_ut_evaluate_object(device_node, METHOD_NAME__CLS,
453
					 ACPI_BTYPE_PACKAGE, &obj_desc);
454
	if (ACPI_FAILURE(status)) {
455
		return_ACPI_STATUS(status);
456
	}
457
 
458
	/* Get the size of the String to be returned, includes null terminator */
459
 
460
	length = ACPI_PCICLS_STRING_SIZE;
461
	cls_objects = obj_desc->package.elements;
462
	count = obj_desc->package.count;
463
 
464
	if (obj_desc->common.type == ACPI_TYPE_PACKAGE) {
465
		if (count > 0
466
		    && cls_objects[0]->common.type == ACPI_TYPE_INTEGER) {
467
			class_code[0] = (u8)cls_objects[0]->integer.value;
468
		}
469
		if (count > 1
470
		    && cls_objects[1]->common.type == ACPI_TYPE_INTEGER) {
471
			class_code[1] = (u8)cls_objects[1]->integer.value;
472
		}
473
		if (count > 2
474
		    && cls_objects[2]->common.type == ACPI_TYPE_INTEGER) {
475
			class_code[2] = (u8)cls_objects[2]->integer.value;
476
		}
477
	}
478
 
479
	/* Allocate a buffer for the CLS */
480
 
481
	cls =
482
	    ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) +
483
				 (acpi_size) length);
484
	if (!cls) {
485
		status = AE_NO_MEMORY;
486
		goto cleanup;
487
	}
488
 
489
	/* Area for the string starts after PNP_DEVICE_ID struct */
490
 
491
	cls->string =
492
	    ACPI_ADD_PTR(char, cls, sizeof(struct acpi_pnp_device_id));
493
 
494
	/* Simply copy existing string */
495
 
496
	acpi_ex_pci_cls_to_string(cls->string, class_code);
497
	cls->length = length;
498
	*return_id = cls;
499
 
500
cleanup:
501
 
502
	/* On exit, we must delete the return object */
503
 
504
	acpi_ut_remove_reference(obj_desc);
505
	return_ACPI_STATUS(status);
506
}