acpi_resource.c revision 96926
160484Sobrien/*-
278828Sobrien * Copyright (c) 2000 Michael Smith
378828Sobrien * Copyright (c) 2000 BSDi
478828Sobrien * All rights reserved.
560484Sobrien *
678828Sobrien * Redistribution and use in source and binary forms, with or without
778828Sobrien * modification, are permitted provided that the following conditions
878828Sobrien * are met:
978828Sobrien * 1. Redistributions of source code must retain the above copyright
1078828Sobrien *    notice, this list of conditions and the following disclaimer.
1178828Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1278828Sobrien *    notice, this list of conditions and the following disclaimer in the
1378828Sobrien *    documentation and/or other materials provided with the distribution.
1478828Sobrien *
1578828Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1678828Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1778828Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1878828Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1978828Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2078828Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2189857Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2289857Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2389857Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2478828Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2560484Sobrien * SUCH DAMAGE.
2689857Sobrien *
2789857Sobrien *	$FreeBSD: head/sys/dev/acpica/acpi_resource.c 96926 2002-05-19 06:16:47Z peter $
2889857Sobrien */
2989857Sobrien
3089857Sobrien#include "opt_acpi.h"
3160484Sobrien#include <sys/param.h>
3260484Sobrien#include <sys/kernel.h>
3360484Sobrien#include <sys/bus.h>
3460484Sobrien
3560484Sobrien#include <machine/bus.h>
3660484Sobrien#include <machine/resource.h>
3760484Sobrien#include <sys/rman.h>
3860484Sobrien
3960484Sobrien#include "acpi.h"
4060484Sobrien
4160484Sobrien#include <dev/acpica/acpivar.h>
4260484Sobrien
4360484Sobrien/*
4460484Sobrien * Hooks for the ACPI CA debugging infrastructure
4560484Sobrien */
4660484Sobrien#define _COMPONENT	ACPI_BUS
4789857SobrienACPI_MODULE_NAME("RESOURCE")
4860484Sobrien
4989857Sobrien/*
5060484Sobrien * Fetch a device's resources and associate them with the device.
5160484Sobrien *
5260484Sobrien * Note that it might be nice to also locate ACPI-specific resource items, such
5360484Sobrien * as GPE bits.
5460484Sobrien *
5560484Sobrien * We really need to split the resource-fetching code out from the
5660484Sobrien * resource-parsing code, since we may want to use the parsing
5760484Sobrien * code for _PRS someday.
5860484Sobrien */
59ACPI_STATUS
60acpi_parse_resources(device_t dev, ACPI_HANDLE handle, struct acpi_parse_resource_set *set)
61{
62    ACPI_BUFFER		buf;
63    ACPI_RESOURCE	*res;
64    char		*curr, *last;
65    ACPI_STATUS		status;
66    void		*context;
67
68    ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
69
70    /*
71     * Special-case some devices that abuse _PRS/_CRS to mean
72     * something other than "I consume this resource".
73     *
74     * XXX do we really need this?  It's only relevant once
75     *     we start always-allocating these resources, and even
76     *     then, the only special-cased device is likely to be
77     *     the PCI interrupt link.
78     */
79
80    /*
81     * Fetch the device's current resources.
82     */
83    buf.Length = ACPI_ALLOCATE_BUFFER;
84    if (ACPI_FAILURE((status = AcpiGetCurrentResources(handle, &buf)))) {
85	if (status != AE_NOT_FOUND)
86	    printf("can't fetch resources for %s - %s\n",
87		   acpi_name(handle), AcpiFormatException(status));
88	return_ACPI_STATUS(status);
89    }
90    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s - got %d bytes of resources\n",
91		      acpi_name(handle), buf.Length));
92    set->set_init(dev, &context);
93
94    /*
95     * Iterate through the resources
96     */
97    curr = buf.Pointer;
98    last = (char *)buf.Pointer + buf.Length;
99    while (curr < last) {
100	res = (ACPI_RESOURCE *)curr;
101	curr += res->Length;
102
103	/*
104	 * Handle the individual resource types
105	 */
106	switch(res->Id) {
107	case ACPI_RSTYPE_END_TAG:
108	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "EndTag\n"));
109	    curr = last;
110	    break;
111
112	case ACPI_RSTYPE_FIXED_IO:
113	    if (res->Data.FixedIo.RangeLength <= 0)
114		break;
115	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedIo 0x%x/%d\n",
116			      res->Data.FixedIo.BaseAddress,
117			      res->Data.FixedIo.RangeLength));
118	    set->set_ioport(dev, context,
119			    res->Data.FixedIo.BaseAddress,
120			    res->Data.FixedIo.RangeLength);
121	    break;
122
123	case ACPI_RSTYPE_IO:
124	    if (res->Data.Io.RangeLength <= 0)
125		break;
126	    if (res->Data.Io.MinBaseAddress == res->Data.Io.MaxBaseAddress) {
127		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x/%d\n",
128				  res->Data.Io.MinBaseAddress,
129				  res->Data.Io.RangeLength));
130		set->set_ioport(dev, context,
131				res->Data.Io.MinBaseAddress,
132				res->Data.Io.RangeLength);
133	    } else {
134		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x-0x%x/%d\n",
135				  res->Data.Io.MinBaseAddress,
136				  res->Data.Io.MaxBaseAddress,
137				  res->Data.Io.RangeLength));
138		set->set_iorange(dev, context,
139				 res->Data.Io.MinBaseAddress,
140				 res->Data.Io.MaxBaseAddress,
141				 res->Data.Io.RangeLength, res->Data.Io.Alignment);
142	    }
143	    break;
144
145	case ACPI_RSTYPE_FIXED_MEM32:
146	    if (res->Data.FixedMemory32.RangeLength <= 0)
147		break;
148	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedMemory32 0x%x/%d\n",
149			      res->Data.FixedMemory32.RangeBaseAddress,
150			      res->Data.FixedMemory32.RangeLength));
151	    set->set_memory(dev, context, res->Data.FixedMemory32.RangeBaseAddress,
152			    res->Data.FixedMemory32.RangeLength);
153	    break;
154
155	case ACPI_RSTYPE_MEM32:
156	    if (res->Data.Memory32.RangeLength <= 0)
157		break;
158	    if (res->Data.Memory32.MinBaseAddress == res->Data.Memory32.MaxBaseAddress) {
159		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x/%d\n",
160				  res->Data.Memory32.MinBaseAddress,
161				  res->Data.Memory32.RangeLength));
162		set->set_memory(dev, context,
163				res->Data.Memory32.MinBaseAddress,
164				res->Data.Memory32.RangeLength);
165	    } else {
166		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x-0x%x/%d\n",
167				  res->Data.Memory32.MinBaseAddress,
168				  res->Data.Memory32.MaxBaseAddress,
169				  res->Data.Memory32.RangeLength));
170		set->set_memoryrange(dev, context,
171				     res->Data.Memory32.MinBaseAddress,
172				     res->Data.Memory32.MaxBaseAddress,
173				     res->Data.Memory32.RangeLength,
174				     res->Data.Memory32.Alignment);
175	    }
176	    break;
177
178	case ACPI_RSTYPE_MEM24:
179	    if (res->Data.Memory24.RangeLength <= 0)
180		break;
181	    if (res->Data.Memory24.MinBaseAddress == res->Data.Memory24.MaxBaseAddress) {
182		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x/%d\n",
183				  res->Data.Memory24.MinBaseAddress,
184				  res->Data.Memory24.RangeLength));
185		set->set_memory(dev, context, res->Data.Memory24.MinBaseAddress,
186				res->Data.Memory24.RangeLength);
187	    } else {
188		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x-0x%x/%d\n",
189				  res->Data.Memory24.MinBaseAddress,
190				  res->Data.Memory24.MaxBaseAddress,
191				  res->Data.Memory24.RangeLength));
192		set->set_memoryrange(dev, context,
193				     res->Data.Memory24.MinBaseAddress,
194				     res->Data.Memory24.MaxBaseAddress,
195				     res->Data.Memory24.RangeLength,
196				     res->Data.Memory24.Alignment);
197	    }
198	    break;
199
200	case ACPI_RSTYPE_IRQ:
201	    /*
202	     * from 1.0b 6.4.2
203	     * "This structure is repeated for each separate interrupt
204	     * required"
205	     */
206	    set->set_irq(dev, context, res->Data.Irq.Interrupts,
207			 res->Data.Irq.NumberOfInterrupts);
208	    break;
209
210	case ACPI_RSTYPE_DMA:
211	    /*
212	     * from 1.0b 6.4.3
213	     * "This structure is repeated for each separate dma channel
214	     * required"
215	     */
216
217	    set->set_drq(dev, context, res->Data.Dma.Channels,
218			 res->Data.Dma.NumberOfChannels);
219	    break;
220
221	case ACPI_RSTYPE_START_DPF:
222	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "start dependant functions\n"));
223	    set->set_start_dependant(dev, context,
224				     res->Data.StartDpf.CompatibilityPriority);
225	    break;
226
227	case ACPI_RSTYPE_END_DPF:
228	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "end dependant functions\n"));
229	    set->set_end_dependant(dev, context);
230	    break;
231
232	case ACPI_RSTYPE_ADDRESS32:
233	    if (res->Data.Address32.AddressLength <= 0)
234		break;
235	    if (res->Data.Address32.ProducerConsumer != ACPI_CONSUMER) {
236		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "ignored Address32 %s producer\n",
237				  (res->Data.Address32.ResourceType == ACPI_IO_RANGE) ?
238				     "IO" : "Memory"));
239		break;
240	    }
241	    if ((res->Data.Address32.ResourceType != ACPI_MEMORY_RANGE) ||
242		(res->Data.Address32.ResourceType != ACPI_IO_RANGE)) {
243		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
244				  "ignored Address32 for non-memory, non-I/O\n"));
245		break;
246	    }
247
248	    if ((res->Data.Address32.MinAddressFixed == ACPI_ADDRESS_FIXED) &&
249		(res->Data.Address32.MaxAddressFixed == ACPI_ADDRESS_FIXED)) {
250		if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) {
251		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address32/Memory 0x%x/%d\n",
252				      res->Data.Address32.MinAddressRange,
253				      res->Data.Address32.AddressLength));
254		    set->set_memory(dev, context,
255				    res->Data.Address32.MinAddressRange,
256				    res->Data.Address32.AddressLength);
257		} else {
258		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address32/IO 0x%x/%d\n",
259				      res->Data.Address32.MinAddressRange,
260				      res->Data.Address32.AddressLength));
261		    set->set_ioport(dev, context,
262				    res->Data.Address32.MinAddressRange,
263				    res->Data.Address32.AddressLength);
264		}
265	    } else {
266		if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) {
267		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address32/Memory 0x%x-0x%x/%d\n",
268				      res->Data.Address32.MinAddressRange,
269				      res->Data.Address32.MaxAddressRange,
270				      res->Data.Address32.AddressLength));
271		    set->set_memoryrange(dev, context,
272					  res->Data.Address32.MinAddressRange,
273					  res->Data.Address32.MaxAddressRange,
274					  res->Data.Address32.AddressLength,
275					  res->Data.Address32.Granularity);
276		} else {
277		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address32/IO 0x%x-0x%x/%d\n",
278				      res->Data.Address32.MinAddressRange,
279				      res->Data.Address32.MaxAddressRange,
280				      res->Data.Address32.AddressLength));
281		    set->set_iorange(dev, context,
282				     res->Data.Address32.MinAddressRange,
283				     res->Data.Address32.MaxAddressRange,
284				     res->Data.Address32.AddressLength,
285				     res->Data.Address32.Granularity);
286		}
287	    }
288	    break;
289
290	case ACPI_RSTYPE_ADDRESS16:
291	    if (res->Data.Address16.AddressLength <= 0)
292		break;
293	    if (res->Data.Address16.ProducerConsumer != ACPI_CONSUMER) {
294		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "ignored Address16 %s producer\n",
295				  (res->Data.Address16.ResourceType == ACPI_IO_RANGE) ?
296				     "IO" : "Memory"));
297		break;
298	    }
299	    if ((res->Data.Address16.ResourceType != ACPI_MEMORY_RANGE) ||
300		(res->Data.Address16.ResourceType != ACPI_IO_RANGE)) {
301		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
302				  "ignored Address16 for non-memory, non-I/O\n"));
303		break;
304	    }
305
306	    if ((res->Data.Address16.MinAddressFixed == ACPI_ADDRESS_FIXED) &&
307		(res->Data.Address16.MaxAddressFixed == ACPI_ADDRESS_FIXED)) {
308		if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) {
309		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address16/Memory 0x%x/%d\n",
310				      res->Data.Address16.MinAddressRange,
311				      res->Data.Address16.AddressLength));
312		    set->set_memory(dev, context,
313				    res->Data.Address16.MinAddressRange,
314				    res->Data.Address16.AddressLength);
315		} else {
316		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address16/IO 0x%x/%d\n",
317				      res->Data.Address16.MinAddressRange,
318				      res->Data.Address16.AddressLength));
319		    set->set_ioport(dev, context,
320				    res->Data.Address16.MinAddressRange,
321				    res->Data.Address16.AddressLength);
322		}
323	    } else {
324		if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) {
325		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address16/Memory 0x%x-0x%x/%d\n",
326				      res->Data.Address16.MinAddressRange,
327				      res->Data.Address16.MaxAddressRange,
328				      res->Data.Address16.AddressLength));
329		    set->set_memoryrange(dev, context,
330					  res->Data.Address16.MinAddressRange,
331					  res->Data.Address16.MaxAddressRange,
332					  res->Data.Address16.AddressLength,
333					  res->Data.Address16.Granularity);
334		} else {
335		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address16/IO 0x%x-0x%x/%d\n",
336				      res->Data.Address16.MinAddressRange,
337				      res->Data.Address16.MaxAddressRange,
338				      res->Data.Address16.AddressLength));
339		    set->set_iorange(dev, context,
340				     res->Data.Address16.MinAddressRange,
341				     res->Data.Address16.MaxAddressRange,
342				     res->Data.Address16.AddressLength,
343				     res->Data.Address16.Granularity);
344		}
345	    }
346	    break;
347
348	case ACPI_RSTYPE_ADDRESS64:
349	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "unimplemented Address64 resource\n"));
350	    break;
351
352	case ACPI_RSTYPE_EXT_IRQ:
353	    /* XXX special handling? */
354	    set->set_irq(dev, context,res->Data.ExtendedIrq.Interrupts,
355			 res->Data.ExtendedIrq.NumberOfInterrupts);
356	    break;
357
358	case ACPI_RSTYPE_VENDOR:
359	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "unimplemented VendorSpecific resource\n"));
360	    break;
361	default:
362	    break;
363	}
364    }
365    AcpiOsFree(buf.Pointer);
366    set->set_done(dev, context);
367    return_ACPI_STATUS(AE_OK);
368}
369
370/*
371 * Resource-set vectors used to attach _CRS-derived resources
372 * to an ACPI device.
373 */
374static void	acpi_res_set_init(device_t dev, void **context);
375static void	acpi_res_set_done(device_t dev, void *context);
376static void	acpi_res_set_ioport(device_t dev, void *context, u_int32_t base, u_int32_t length);
377static void	acpi_res_set_iorange(device_t dev, void *context, u_int32_t low, u_int32_t high,
378				     u_int32_t length, u_int32_t align);
379static void	acpi_res_set_memory(device_t dev, void *context, u_int32_t base, u_int32_t length);
380static void	acpi_res_set_memoryrange(device_t dev, void *context, u_int32_t low, u_int32_t high,
381					 u_int32_t length, u_int32_t align);
382static void	acpi_res_set_irq(device_t dev, void *context, u_int32_t *irq,
383				 int count);
384static void	acpi_res_set_drq(device_t dev, void *context, u_int32_t *drq,
385				 int count);
386static void	acpi_res_set_start_dependant(device_t dev, void *context, int preference);
387static void	acpi_res_set_end_dependant(device_t dev, void *context);
388
389struct acpi_parse_resource_set acpi_res_parse_set = {
390    acpi_res_set_init,
391    acpi_res_set_done,
392    acpi_res_set_ioport,
393    acpi_res_set_iorange,
394    acpi_res_set_memory,
395    acpi_res_set_memoryrange,
396    acpi_res_set_irq,
397    acpi_res_set_drq,
398    acpi_res_set_start_dependant,
399    acpi_res_set_end_dependant
400};
401
402struct acpi_res_context {
403    int		ar_nio;
404    int		ar_nmem;
405    int		ar_nirq;
406    int		ar_ndrq;
407};
408
409static void
410acpi_res_set_init(device_t dev, void **context)
411{
412    struct acpi_res_context	*cp;
413
414    if ((cp = AcpiOsAllocate(sizeof(*cp))) != NULL) {
415	bzero(cp, sizeof(*cp));
416	*context = cp;
417    }
418}
419
420static void
421acpi_res_set_done(device_t dev, void *context)
422{
423    struct acpi_res_context	*cp = (struct acpi_res_context *)context;
424
425    if (cp == NULL)
426	return;
427    AcpiOsFree(cp);
428}
429
430static void
431acpi_res_set_ioport(device_t dev, void *context, u_int32_t base, u_int32_t length)
432{
433    struct acpi_res_context	*cp = (struct acpi_res_context *)context;
434
435    if (cp == NULL)
436	return;
437    bus_set_resource(dev, SYS_RES_IOPORT, cp->ar_nio++, base, length);
438}
439
440static void
441acpi_res_set_iorange(device_t dev, void *context, u_int32_t low, u_int32_t high, u_int32_t length, u_int32_t align)
442{
443    struct acpi_res_context	*cp = (struct acpi_res_context *)context;
444
445    if (cp == NULL)
446	return;
447    device_printf(dev, "I/O range not supported\n");
448}
449
450static void
451acpi_res_set_memory(device_t dev, void *context, u_int32_t base, u_int32_t length)
452{
453    struct acpi_res_context	*cp = (struct acpi_res_context *)context;
454
455    if (cp == NULL)
456	return;
457
458    bus_set_resource(dev, SYS_RES_MEMORY, cp->ar_nmem++, base, length);
459}
460
461static void
462acpi_res_set_memoryrange(device_t dev, void *context, u_int32_t low, u_int32_t high, u_int32_t length, u_int32_t align)
463{
464    struct acpi_res_context	*cp = (struct acpi_res_context *)context;
465
466    if (cp == NULL)
467	return;
468    device_printf(dev, "memory range not supported\n");
469}
470
471static void
472acpi_res_set_irq(device_t dev, void *context, u_int32_t *irq, int count)
473{
474    struct acpi_res_context	*cp = (struct acpi_res_context *)context;
475
476    if (cp == NULL)
477	return;
478    if (irq == NULL)
479	return;
480
481    /*This implements no resource relocation.*/
482    if(count != 1)
483	return;
484
485    bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1);
486}
487
488static void
489acpi_res_set_drq(device_t dev, void *context, u_int32_t *drq, int count)
490{
491    struct acpi_res_context	*cp = (struct acpi_res_context *)context;
492
493    if (cp == NULL)
494	return;
495    if (drq == NULL)
496	return;
497
498    /*This implements no resource relocation.*/
499    if(count != 1)
500	return;
501
502    bus_set_resource(dev, SYS_RES_DRQ, cp->ar_ndrq++, *drq, 1);
503}
504
505static void
506acpi_res_set_start_dependant(device_t dev, void *context, int preference)
507{
508    struct acpi_res_context	*cp = (struct acpi_res_context *)context;
509
510    if (cp == NULL)
511	return;
512    device_printf(dev, "dependant functions not supported\n");
513}
514
515static void
516acpi_res_set_end_dependant(device_t dev, void *context)
517{
518    struct acpi_res_context	*cp = (struct acpi_res_context *)context;
519
520    if (cp == NULL)
521	return;
522}
523
524/*
525 * Resource-owning placeholders.
526 *
527 * This code "owns" system resource objects that aren't
528 * otherwise useful to devices, and which shouldn't be
529 * considered "free".
530 *
531 * Note that some systems claim *all* of the physical address space
532 * with a PNP0C01 device, so we cannot correctly "own" system memory
533 * here (must be done in the SMAP handler on x86 systems, for
534 * example).
535 */
536
537static int	acpi_sysresource_probe(device_t dev);
538static int	acpi_sysresource_attach(device_t dev);
539
540static device_method_t acpi_sysresource_methods[] = {
541    /* Device interface */
542    DEVMETHOD(device_probe,	acpi_sysresource_probe),
543    DEVMETHOD(device_attach,	acpi_sysresource_attach),
544
545    {0, 0}
546};
547
548static driver_t acpi_sysresource_driver = {
549    "acpi_sysresource",
550    acpi_sysresource_methods,
551    0,
552};
553
554static devclass_t acpi_sysresource_devclass;
555DRIVER_MODULE(acpi_sysresource, acpi, acpi_sysresource_driver, acpi_sysresource_devclass, 0, 0);
556
557static int
558acpi_sysresource_probe(device_t dev)
559{
560    if (acpi_disabled("sysresource"))
561	return(ENXIO);
562    if (acpi_MatchHid(dev, "PNP0C02")) {
563	device_set_desc(dev, "system resource");
564    } else {
565	return(ENXIO);
566    }
567    device_quiet(dev);
568    return(-100);
569}
570
571static int
572acpi_sysresource_attach(device_t dev)
573{
574    struct resource	*res;
575    int			i, rid;
576
577    /*
578     * Suck up all the resources that might have been assigned to us.
579     * Note that it's impossible to tell the difference between a
580     * resource that someone else has claimed, and one that doesn't
581     * exist.
582     */
583    for (i = 0; i < 100; i++) {
584	rid = i;
585	res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, 0);
586	rid = i;
587	res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0, 1, 0);
588	rid = i;
589	res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_SHAREABLE);
590    }
591    return(0);
592}
593