Added
Link Here
|
1 |
/* |
2 |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
3 |
* This program is free software; you can redistribute it and/or modify |
4 |
* it under the terms of the GNU General Public License as published by |
5 |
* the Free Software Foundation; either version 2 of the License, or (at |
6 |
* your option) any later version. |
7 |
* |
8 |
* This program is distributed in the hope that it will be useful, but |
9 |
* WITHOUT ANY WARRANTY; without even the implied warranty of |
10 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
11 |
* General Public License for more details. |
12 |
* |
13 |
* You should have received a copy of the GNU General Public License along |
14 |
* with this program; if not, write to the Free Software Foundation, Inc., |
15 |
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
16 |
* |
17 |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
18 |
*/ |
19 |
|
20 |
#include <linux/kernel.h> |
21 |
#include <linux/init.h> |
22 |
#include <linux/types.h> |
23 |
#include <linux/pci.h> |
24 |
#include <linux/ioport.h> |
25 |
#include <asm/io.h> |
26 |
|
27 |
#include <acpi/acpi_bus.h> |
28 |
#include <acpi/acpi_drivers.h> |
29 |
|
30 |
#define _COMPONENT ACPI_SYSTEM_COMPONENT |
31 |
ACPI_MODULE_NAME ("acpi_motherboard") |
32 |
|
33 |
/* Dell use PNP0C01 instead of PNP0C02 */ |
34 |
#define ACPI_MB_HID1 "PNP0C01" |
35 |
#define ACPI_MB_HID2 "PNP0C02" |
36 |
|
37 |
/** |
38 |
* Doesn't care about legacy IO ports, only IO ports beyond 0x1000 are reserved |
39 |
* Doesn't care about the failure of 'request_region', since other may reserve |
40 |
* the io ports as well |
41 |
*/ |
42 |
#define IS_RESERVED_ADDR(base, len) \ |
43 |
(((len) > 0) && ((base) > 0) && ((base) + (len) < IO_SPACE_LIMIT) \ |
44 |
&& ((base) + (len) > PCIBIOS_MIN_IO)) |
45 |
|
46 |
static acpi_status |
47 |
acpi_reserve_io_ranges (struct acpi_resource *res, void *data) |
48 |
{ |
49 |
ACPI_FUNCTION_TRACE("acpi_reserve_io_ranges"); |
50 |
|
51 |
if (res->id == ACPI_RSTYPE_IO) { |
52 |
struct acpi_resource_io *io_res = &res->data.io; |
53 |
|
54 |
if (io_res->min_base_address != io_res->max_base_address) |
55 |
return AE_OK; |
56 |
if (IS_RESERVED_ADDR(io_res->min_base_address, io_res->range_length)) { |
57 |
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Motherboard resources 0x%08x - 0x%08x\n", |
58 |
io_res->min_base_address, |
59 |
io_res->min_base_address + io_res->range_length)); |
60 |
request_region(io_res->min_base_address, |
61 |
io_res->range_length, "motherboard"); |
62 |
} |
63 |
}else if (res->id == ACPI_RSTYPE_FIXED_IO) { |
64 |
struct acpi_resource_fixed_io *fixed_io_res = &res->data.fixed_io; |
65 |
|
66 |
if (IS_RESERVED_ADDR(fixed_io_res->base_address, fixed_io_res->range_length)) { |
67 |
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Motherboard resources 0x%08x - 0x%08x\n", |
68 |
fixed_io_res->base_address, |
69 |
fixed_io_res->base_address + fixed_io_res->range_length)); |
70 |
request_region(fixed_io_res->base_address, |
71 |
fixed_io_res->range_length, "motherboard"); |
72 |
} |
73 |
}else { |
74 |
/* Memory mapped IO? */ |
75 |
} |
76 |
|
77 |
return AE_OK; |
78 |
} |
79 |
|
80 |
static int acpi_motherboard_add (struct acpi_device *device) |
81 |
{ |
82 |
if (!device) |
83 |
return -EINVAL; |
84 |
acpi_walk_resources(device->handle, METHOD_NAME__CRS, |
85 |
acpi_reserve_io_ranges, NULL); |
86 |
|
87 |
return 0; |
88 |
} |
89 |
|
90 |
static struct acpi_driver acpi_motherboard_driver1 = { |
91 |
.name = "motherboard", |
92 |
.class = "", |
93 |
.ids = ACPI_MB_HID1, |
94 |
.ops = { |
95 |
.add = acpi_motherboard_add, |
96 |
}, |
97 |
}; |
98 |
|
99 |
static struct acpi_driver acpi_motherboard_driver2 = { |
100 |
.name = "motherboard", |
101 |
.class = "", |
102 |
.ids = ACPI_MB_HID2, |
103 |
.ops = { |
104 |
.add = acpi_motherboard_add, |
105 |
}, |
106 |
}; |
107 |
|
108 |
static void __init |
109 |
acpi_reserve_resources (void) |
110 |
{ |
111 |
if (acpi_gbl_FADT->xpm1a_evt_blk.address && acpi_gbl_FADT->pm1_evt_len) |
112 |
request_region(acpi_gbl_FADT->xpm1a_evt_blk.address, |
113 |
acpi_gbl_FADT->pm1_evt_len, "PM1a_EVT_BLK"); |
114 |
|
115 |
if (acpi_gbl_FADT->xpm1b_evt_blk.address && acpi_gbl_FADT->pm1_evt_len) |
116 |
request_region(acpi_gbl_FADT->xpm1b_evt_blk.address, |
117 |
acpi_gbl_FADT->pm1_evt_len, "PM1b_EVT_BLK"); |
118 |
|
119 |
if (acpi_gbl_FADT->xpm1a_cnt_blk.address && acpi_gbl_FADT->pm1_cnt_len) |
120 |
request_region(acpi_gbl_FADT->xpm1a_cnt_blk.address, |
121 |
acpi_gbl_FADT->pm1_cnt_len, "PM1a_CNT_BLK"); |
122 |
|
123 |
if (acpi_gbl_FADT->xpm1b_cnt_blk.address && acpi_gbl_FADT->pm1_cnt_len) |
124 |
request_region(acpi_gbl_FADT->xpm1b_cnt_blk.address, |
125 |
acpi_gbl_FADT->pm1_cnt_len, "PM1b_CNT_BLK"); |
126 |
|
127 |
if (acpi_gbl_FADT->xpm_tmr_blk.address && acpi_gbl_FADT->pm_tm_len == 4) |
128 |
request_region(acpi_gbl_FADT->xpm_tmr_blk.address, |
129 |
4, "PM_TMR"); |
130 |
|
131 |
if (acpi_gbl_FADT->xpm2_cnt_blk.address && acpi_gbl_FADT->pm2_cnt_len) |
132 |
request_region(acpi_gbl_FADT->xpm2_cnt_blk.address, |
133 |
acpi_gbl_FADT->pm2_cnt_len, "PM2_CNT_BLK"); |
134 |
|
135 |
/* Length of GPE blocks must be a non-negative multiple of 2 */ |
136 |
|
137 |
if (acpi_gbl_FADT->xgpe0_blk.address && acpi_gbl_FADT->gpe0_blk_len && |
138 |
!(acpi_gbl_FADT->gpe0_blk_len & 0x1)) |
139 |
request_region(acpi_gbl_FADT->xgpe0_blk.address, |
140 |
acpi_gbl_FADT->gpe0_blk_len, "GPE0_BLK"); |
141 |
|
142 |
if (acpi_gbl_FADT->xgpe1_blk.address && acpi_gbl_FADT->gpe1_blk_len && |
143 |
!(acpi_gbl_FADT->gpe1_blk_len & 0x1)) |
144 |
request_region(acpi_gbl_FADT->xgpe1_blk.address, |
145 |
acpi_gbl_FADT->gpe1_blk_len, "GPE1_BLK"); |
146 |
} |
147 |
|
148 |
static int __init acpi_motherboard_init(void) |
149 |
{ |
150 |
acpi_bus_register_driver(&acpi_motherboard_driver1); |
151 |
acpi_bus_register_driver(&acpi_motherboard_driver2); |
152 |
/* |
153 |
* Guarantee motherboard IO reservation first |
154 |
* This module must run after scan.c |
155 |
*/ |
156 |
if (!acpi_disabled) |
157 |
acpi_reserve_resources (); |
158 |
return 0; |
159 |
} |
160 |
|
161 |
subsys_initcall(acpi_motherboard_init); |