PageRenderTime 34ms CodeModel.GetById 14ms app.highlight 15ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/acpi/motherboard.c

https://bitbucket.org/evzijst/gittest
C | 177 lines | 109 code | 28 blank | 40 comment | 33 complexity | cd543c37d1432a869fd1b1cfb0d60ccc MD5 | raw file
  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/* Purpose: Prevent PCMCIA cards from using motherboard resources. */
 21
 22#include <linux/kernel.h>
 23#include <linux/init.h>
 24#include <linux/types.h>
 25#include <linux/pci.h>
 26#include <linux/ioport.h>
 27#include <asm/io.h>
 28
 29#include <acpi/acpi_bus.h>
 30#include <acpi/acpi_drivers.h>
 31
 32#define _COMPONENT		ACPI_SYSTEM_COMPONENT
 33ACPI_MODULE_NAME		("acpi_motherboard")
 34
 35/* Dell use PNP0C01 instead of PNP0C02 */
 36#define ACPI_MB_HID1			"PNP0C01"
 37#define ACPI_MB_HID2			"PNP0C02"
 38
 39/**
 40 * Doesn't care about legacy IO ports, only IO ports beyond 0x1000 are reserved
 41 * Doesn't care about the failure of 'request_region', since other may reserve 
 42 * the io ports as well
 43 */
 44#define IS_RESERVED_ADDR(base, len) \
 45	(((len) > 0) && ((base) > 0) && ((base) + (len) < IO_SPACE_LIMIT) \
 46	&& ((base) + (len) > PCIBIOS_MIN_IO))
 47
 48/*
 49 * Clearing the flag (IORESOURCE_BUSY) allows drivers to use
 50 * the io ports if they really know they can use it, while
 51 * still preventing hotplug PCI devices from using it. 
 52 */
 53
 54static acpi_status
 55acpi_reserve_io_ranges (struct acpi_resource *res, void *data)
 56{
 57	struct resource *requested_res = NULL;
 58
 59	ACPI_FUNCTION_TRACE("acpi_reserve_io_ranges");
 60
 61	if (res->id == ACPI_RSTYPE_IO) {
 62		struct acpi_resource_io *io_res = &res->data.io;
 63
 64		if (io_res->min_base_address != io_res->max_base_address)
 65			return_VALUE(AE_OK);
 66		if (IS_RESERVED_ADDR(io_res->min_base_address, io_res->range_length)) {
 67			ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Motherboard resources 0x%08x - 0x%08x\n",
 68				io_res->min_base_address, 
 69				io_res->min_base_address + io_res->range_length));
 70			requested_res = request_region(io_res->min_base_address, 
 71				io_res->range_length, "motherboard");
 72		}
 73	} else if (res->id == ACPI_RSTYPE_FIXED_IO) {
 74		struct acpi_resource_fixed_io *fixed_io_res = &res->data.fixed_io;
 75
 76		if (IS_RESERVED_ADDR(fixed_io_res->base_address, fixed_io_res->range_length)) {
 77			ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Motherboard resources 0x%08x - 0x%08x\n",
 78				fixed_io_res->base_address, 
 79				fixed_io_res->base_address + fixed_io_res->range_length));
 80			requested_res = request_region(fixed_io_res->base_address, 
 81				fixed_io_res->range_length, "motherboard");
 82		}
 83	} else {
 84		/* Memory mapped IO? */
 85	}
 86
 87	if (requested_res)
 88		requested_res->flags &= ~IORESOURCE_BUSY;
 89	return_VALUE(AE_OK);
 90}
 91
 92static int acpi_motherboard_add (struct acpi_device *device)
 93{
 94	if (!device)
 95		return -EINVAL;
 96	acpi_walk_resources(device->handle, METHOD_NAME__CRS, 
 97		acpi_reserve_io_ranges, NULL);
 98
 99	return 0;
100}
101
102static struct acpi_driver acpi_motherboard_driver1 = {
103	.name =		"motherboard",
104	.class =	"",
105	.ids =		ACPI_MB_HID1,
106	.ops =	{
107		.add =		acpi_motherboard_add,
108	},
109};
110
111static struct acpi_driver acpi_motherboard_driver2 = {
112	.name =		"motherboard",
113	.class =	"",
114	.ids =		ACPI_MB_HID2,
115	.ops =	{
116		.add =		acpi_motherboard_add,
117	},
118};
119
120static void __init
121acpi_reserve_resources (void)
122{
123	if (acpi_gbl_FADT->xpm1a_evt_blk.address && acpi_gbl_FADT->pm1_evt_len)
124		request_region(acpi_gbl_FADT->xpm1a_evt_blk.address, 
125			acpi_gbl_FADT->pm1_evt_len, "PM1a_EVT_BLK");
126
127	if (acpi_gbl_FADT->xpm1b_evt_blk.address && acpi_gbl_FADT->pm1_evt_len)
128		request_region(acpi_gbl_FADT->xpm1b_evt_blk.address,
129			acpi_gbl_FADT->pm1_evt_len, "PM1b_EVT_BLK");
130
131	if (acpi_gbl_FADT->xpm1a_cnt_blk.address && acpi_gbl_FADT->pm1_cnt_len)
132		request_region(acpi_gbl_FADT->xpm1a_cnt_blk.address, 
133			acpi_gbl_FADT->pm1_cnt_len, "PM1a_CNT_BLK");
134
135	if (acpi_gbl_FADT->xpm1b_cnt_blk.address && acpi_gbl_FADT->pm1_cnt_len)
136		request_region(acpi_gbl_FADT->xpm1b_cnt_blk.address, 
137			acpi_gbl_FADT->pm1_cnt_len, "PM1b_CNT_BLK");
138
139	if (acpi_gbl_FADT->xpm_tmr_blk.address && acpi_gbl_FADT->pm_tm_len == 4)
140		request_region(acpi_gbl_FADT->xpm_tmr_blk.address,
141			4, "PM_TMR");
142
143	if (acpi_gbl_FADT->xpm2_cnt_blk.address && acpi_gbl_FADT->pm2_cnt_len)
144		request_region(acpi_gbl_FADT->xpm2_cnt_blk.address,
145			acpi_gbl_FADT->pm2_cnt_len, "PM2_CNT_BLK");
146
147	/* Length of GPE blocks must be a non-negative multiple of 2 */
148
149	if (acpi_gbl_FADT->xgpe0_blk.address && acpi_gbl_FADT->gpe0_blk_len &&
150			!(acpi_gbl_FADT->gpe0_blk_len & 0x1))
151		request_region(acpi_gbl_FADT->xgpe0_blk.address,
152			acpi_gbl_FADT->gpe0_blk_len, "GPE0_BLK");
153
154	if (acpi_gbl_FADT->xgpe1_blk.address && acpi_gbl_FADT->gpe1_blk_len &&
155			!(acpi_gbl_FADT->gpe1_blk_len & 0x1))
156		request_region(acpi_gbl_FADT->xgpe1_blk.address,
157			acpi_gbl_FADT->gpe1_blk_len, "GPE1_BLK");
158}
159
160static int __init acpi_motherboard_init(void)
161{
162	acpi_bus_register_driver(&acpi_motherboard_driver1);
163	acpi_bus_register_driver(&acpi_motherboard_driver2);
164	/* 
165	 * Guarantee motherboard IO reservation first
166	 * This module must run after scan.c
167	 */
168	if (!acpi_disabled)
169		acpi_reserve_resources ();
170	return 0;
171}
172
173/**
174 * Reserve motherboard resources after PCI claim BARs,
175 * but before PCI assign resources for uninitialized PCI devices
176 */
177fs_initcall(acpi_motherboard_init);