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
);