2 * ACPI PCI HotPlug PCI configuration space management
4 * Copyright (C) 1995,2001 Compaq Computer Corporation
5 * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
6 * Copyright (C) 2001,2002 IBM Corp.
7 * Copyright (C) 2002 Takayoshi Kochi (t-kochi@bq.jp.nec.com)
8 * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
9 * Copyright (C) 2002 NEC Corporation
11 * All rights reserved.
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or (at
16 * your option) any later version.
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
21 * NON INFRINGEMENT. See the GNU General Public License for more
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 * Send feedback to <t-kochi@bq.jp.nec.com>
32 #include <linux/init.h>
33 #include <linux/module.h>
35 #include <linux/kernel.h>
36 #include <linux/pci.h>
37 #include <linux/acpi.h>
39 #include "pci_hotplug.h"
42 #define MY_NAME "acpiphp_pci"
45 /* allocate mem/pmem/io resource to a new function */
46 static int init_config_space (struct acpiphp_func *func)
59 struct acpiphp_bridge *bridge;
60 struct pci_resource *res;
62 int bus, device, function;
66 bridge = func->slot->bridge;
67 pbus = bridge->pci_bus;
69 device = func->slot->device;
70 function = func->function;
71 devfn = PCI_DEVFN(device, function);
73 for (count = 0; address[count]; count++) { /* for 6 BARs */
74 pci_bus_write_config_dword(pbus, devfn,
75 address[count], 0xFFFFFFFF);
76 pci_bus_read_config_dword(pbus, devfn, address[count], &bar);
78 if (!bar) /* This BAR is not implemented */
81 dbg("Device %02x.%02x BAR %d wants %x\n", device, function, count, bar);
83 if (bar & PCI_BASE_ADDRESS_SPACE_IO) {
86 len = bar & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF);
87 len = len & ~(len - 1);
89 dbg("len in IO %x, BAR %d\n", len, count);
91 spin_lock(&bridge->res_lock);
92 res = acpiphp_get_io_resource(&bridge->io_head, len);
93 spin_unlock(&bridge->res_lock);
96 err("cannot allocate requested io for %02x:%02x.%d len %x\n",
97 bus, device, function, len);
100 pci_bus_write_config_dword(pbus, devfn,
103 res->next = func->io_head;
108 if (bar & PCI_BASE_ADDRESS_MEM_PREFETCH) {
111 len = bar & 0xFFFFFFF0;
114 dbg("len in PFMEM %x, BAR %d\n", len, count);
116 spin_lock(&bridge->res_lock);
117 res = acpiphp_get_resource(&bridge->p_mem_head, len);
118 spin_unlock(&bridge->res_lock);
121 err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n",
122 bus, device, function, len);
126 pci_bus_write_config_dword(pbus, devfn,
130 if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */
131 dbg("inside the pfmem 64 case, count %d\n", count);
133 pci_bus_write_config_dword(pbus, devfn,
135 (u32)(res->base >> 32));
138 res->next = func->p_mem_head;
139 func->p_mem_head = res;
144 len = bar & 0xFFFFFFF0;
147 dbg("len in MEM %x, BAR %d\n", len, count);
149 spin_lock(&bridge->res_lock);
150 res = acpiphp_get_resource(&bridge->mem_head, len);
151 spin_unlock(&bridge->res_lock);
154 err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n",
155 bus, device, function, len);
159 pci_bus_write_config_dword(pbus, devfn,
163 if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) {
164 /* takes up another dword */
165 dbg("inside mem 64 case, reg. mem, count %d\n", count);
167 pci_bus_write_config_dword(pbus, devfn,
169 (u32)(res->base >> 32));
172 res->next = func->mem_head;
173 func->mem_head = res;
179 /* disable expansion rom */
180 pci_bus_write_config_dword(pbus, devfn, PCI_ROM_ADDRESS, 0x00000000);
182 /* set PCI parameters from _HPP */
183 pci_bus_write_config_byte(pbus, devfn, PCI_CACHE_LINE_SIZE,
184 bridge->hpp.cache_line_size);
185 pci_bus_write_config_byte(pbus, devfn, PCI_LATENCY_TIMER,
186 bridge->hpp.latency_timer);
188 pci_bus_read_config_word(pbus, devfn, PCI_COMMAND, &tmp);
189 if (bridge->hpp.enable_SERR)
190 tmp |= PCI_COMMAND_SERR;
191 if (bridge->hpp.enable_PERR)
192 tmp |= PCI_COMMAND_PARITY;
193 pci_bus_write_config_word(pbus, devfn, PCI_COMMAND, tmp);
198 /* detect_used_resource - subtract resource under dev from bridge */
199 static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *dev)
203 dbg("Device %s\n", pci_name(dev));
205 for (count = 0; count < DEVICE_COUNT_RESOURCE; count++) {
206 struct pci_resource *res;
207 struct pci_resource **head;
208 unsigned long base = dev->resource[count].start;
209 unsigned long len = dev->resource[count].end - base + 1;
210 unsigned long flags = dev->resource[count].flags;
215 dbg("BAR[%d] 0x%lx - 0x%lx (0x%lx)\n", count, base,
216 base + len - 1, flags);
218 if (flags & IORESOURCE_IO) {
219 head = &bridge->io_head;
220 } else if (flags & IORESOURCE_PREFETCH) {
221 head = &bridge->p_mem_head;
223 head = &bridge->mem_head;
226 spin_lock(&bridge->res_lock);
227 res = acpiphp_get_resource_with_base(head, base, len);
228 spin_unlock(&bridge->res_lock);
238 * acpiphp_detect_pci_resource - detect resources under bridge
239 * @bridge: detect all resources already used under this bridge
241 * collect all resources already allocated for all devices under a bridge.
243 int acpiphp_detect_pci_resource (struct acpiphp_bridge *bridge)
248 list_for_each (l, &bridge->pci_bus->devices) {
250 detect_used_resource(bridge, dev);
258 * acpiphp_init_slot_resource - gather resource usage information of a slot
259 * @slot: ACPI slot object to be checked, should have valid pci_dev member
261 * TBD: PCI-to-PCI bridge case
262 * use pci_dev->resource[]
264 int acpiphp_init_func_resource (struct acpiphp_func *func)
278 struct pci_resource *res;
282 dbg("Hot-pluggable device %s\n", pci_name(dev));
284 for (count = 0; address[count]; count++) { /* for 6 BARs */
285 pci_read_config_dword(dev, address[count], &bar);
287 if (!bar) /* This BAR is not implemented */
290 pci_write_config_dword(dev, address[count], 0xFFFFFFFF);
291 pci_read_config_dword(dev, address[count], &len);
293 if (len & PCI_BASE_ADDRESS_SPACE_IO) {
295 base = bar & 0xFFFFFFFC;
296 len = len & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF);
297 len = len & ~(len - 1);
299 dbg("BAR[%d] %08x - %08x (IO)\n", count, (u32)base, (u32)base + len - 1);
301 res = acpiphp_make_resource(base, len);
305 res->next = func->io_head;
310 base = bar & 0xFFFFFFF0;
311 if (len & PCI_BASE_ADDRESS_MEM_PREFETCH) {
317 if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */
318 dbg("prefetch mem 64\n");
321 dbg("BAR[%d] %08x - %08x (PMEM)\n", count, (u32)base, (u32)base + len - 1);
322 res = acpiphp_make_resource(base, len);
326 res->next = func->p_mem_head;
327 func->p_mem_head = res;
335 if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {
336 /* takes up another dword */
340 dbg("BAR[%d] %08x - %08x (MEM)\n", count, (u32)base, (u32)base + len - 1);
341 res = acpiphp_make_resource(base, len);
345 res->next = func->mem_head;
346 func->mem_head = res;
351 pci_write_config_dword(dev, address[count], bar);
354 acpiphp_dump_func_resource(func);
360 err("out of memory\n");
361 acpiphp_free_resource(&func->io_head);
362 acpiphp_free_resource(&func->mem_head);
363 acpiphp_free_resource(&func->p_mem_head);
370 * acpiphp_configure_slot - allocate PCI resources
371 * @slot: slot to be configured
373 * initializes a PCI functions on a device inserted
377 int acpiphp_configure_slot (struct acpiphp_slot *slot)
379 struct acpiphp_func *func;
386 pci_bus_read_config_byte(slot->bridge->pci_bus,
387 PCI_DEVFN(slot->device, 0),
388 PCI_HEADER_TYPE, &hdr);
393 list_for_each (l, &slot->funcs) {
394 func = list_entry(l, struct acpiphp_func, sibling);
395 if (is_multi || func->function == 0) {
396 pci_bus_read_config_dword(slot->bridge->pci_bus,
397 PCI_DEVFN(slot->device,
399 PCI_VENDOR_ID, &dvid);
400 if (dvid != 0xffffffff) {
401 retval = init_config_space(func);
412 * acpiphp_configure_function - configure PCI function
413 * @func: function to be configured
415 * initializes a PCI functions on a device inserted
419 int acpiphp_configure_function (struct acpiphp_func *func)
421 /* all handled by the pci core now */
426 * acpiphp_unconfigure_function - unconfigure PCI function
427 * @func: function to be unconfigured
430 void acpiphp_unconfigure_function (struct acpiphp_func *func)
432 struct acpiphp_bridge *bridge;
434 /* if pci_dev is NULL, ignore it */
438 pci_remove_bus_device(func->pci_dev);
440 /* free all resources */
441 bridge = func->slot->bridge;
443 spin_lock(&bridge->res_lock);
444 acpiphp_move_resource(&func->io_head, &bridge->io_head);
445 acpiphp_move_resource(&func->mem_head, &bridge->mem_head);
446 acpiphp_move_resource(&func->p_mem_head, &bridge->p_mem_head);
447 acpiphp_move_resource(&func->bus_head, &bridge->bus_head);
448 spin_unlock(&bridge->res_lock);