ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / pci / hotplug / acpiphp_pci.c
1 /*
2  * ACPI PCI HotPlug PCI configuration space management
3  *
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
10  *
11  * All rights reserved.
12  *
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.
17  *
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
22  * details.
23  *
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.
27  *
28  * Send feedback to <t-kochi@bq.jp.nec.com>
29  *
30  */
31
32 #include <linux/init.h>
33 #include <linux/module.h>
34
35 #include <linux/kernel.h>
36 #include <linux/pci.h>
37 #include <linux/acpi.h>
38 #include "../pci.h"
39 #include "pci_hotplug.h"
40 #include "acpiphp.h"
41
42 #define MY_NAME "acpiphp_pci"
43
44
45 /* allocate mem/pmem/io resource to a new function */
46 static int init_config_space (struct acpiphp_func *func)
47 {
48         u32 bar, len;
49         u32 address[] = {
50                 PCI_BASE_ADDRESS_0,
51                 PCI_BASE_ADDRESS_1,
52                 PCI_BASE_ADDRESS_2,
53                 PCI_BASE_ADDRESS_3,
54                 PCI_BASE_ADDRESS_4,
55                 PCI_BASE_ADDRESS_5,
56                 0
57         };
58         int count;
59         struct acpiphp_bridge *bridge;
60         struct pci_resource *res;
61         struct pci_bus *pbus;
62         int bus, device, function;
63         unsigned int devfn;
64         u16 tmp;
65
66         bridge = func->slot->bridge;
67         pbus = bridge->pci_bus;
68         bus = bridge->bus;
69         device = func->slot->device;
70         function = func->function;
71         devfn = PCI_DEVFN(device, function);
72
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);
77
78                 if (!bar)       /* This BAR is not implemented */
79                         continue;
80
81                 dbg("Device %02x.%02x BAR %d wants %x\n", device, function, count, bar);
82
83                 if (bar & PCI_BASE_ADDRESS_SPACE_IO) {
84                         /* This is IO */
85
86                         len = bar & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF);
87                         len = len & ~(len - 1);
88
89                         dbg("len in IO %x, BAR %d\n", len, count);
90
91                         spin_lock(&bridge->res_lock);
92                         res = acpiphp_get_io_resource(&bridge->io_head, len);
93                         spin_unlock(&bridge->res_lock);
94
95                         if (!res) {
96                                 err("cannot allocate requested io for %02x:%02x.%d len %x\n",
97                                     bus, device, function, len);
98                                 return -1;
99                         }
100                         pci_bus_write_config_dword(pbus, devfn,
101                                                    address[count],
102                                                    (u32)res->base);
103                         res->next = func->io_head;
104                         func->io_head = res;
105
106                 } else {
107                         /* This is Memory */
108                         if (bar & PCI_BASE_ADDRESS_MEM_PREFETCH) {
109                                 /* pfmem */
110
111                                 len = bar & 0xFFFFFFF0;
112                                 len = ~len + 1;
113
114                                 dbg("len in PFMEM %x, BAR %d\n", len, count);
115
116                                 spin_lock(&bridge->res_lock);
117                                 res = acpiphp_get_resource(&bridge->p_mem_head, len);
118                                 spin_unlock(&bridge->res_lock);
119
120                                 if (!res) {
121                                         err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n",
122                                             bus, device, function, len);
123                                         return -1;
124                                 }
125
126                                 pci_bus_write_config_dword(pbus, devfn,
127                                                            address[count],
128                                                            (u32)res->base);
129
130                                 if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) {       /* takes up another dword */
131                                         dbg("inside the pfmem 64 case, count %d\n", count);
132                                         count += 1;
133                                         pci_bus_write_config_dword(pbus, devfn,
134                                                                    address[count],
135                                                                    (u32)(res->base >> 32));
136                                 }
137
138                                 res->next = func->p_mem_head;
139                                 func->p_mem_head = res;
140
141                         } else {
142                                 /* regular memory */
143
144                                 len = bar & 0xFFFFFFF0;
145                                 len = ~len + 1;
146
147                                 dbg("len in MEM %x, BAR %d\n", len, count);
148
149                                 spin_lock(&bridge->res_lock);
150                                 res = acpiphp_get_resource(&bridge->mem_head, len);
151                                 spin_unlock(&bridge->res_lock);
152
153                                 if (!res) {
154                                         err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n",
155                                             bus, device, function, len);
156                                         return -1;
157                                 }
158
159                                 pci_bus_write_config_dword(pbus, devfn,
160                                                            address[count],
161                                                            (u32)res->base);
162
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);
166                                         count += 1;
167                                         pci_bus_write_config_dword(pbus, devfn,
168                                                                    address[count],
169                                                                    (u32)(res->base >> 32));
170                                 }
171
172                                 res->next = func->mem_head;
173                                 func->mem_head = res;
174
175                         }
176                 }
177         }
178
179         /* disable expansion rom */
180         pci_bus_write_config_dword(pbus, devfn, PCI_ROM_ADDRESS, 0x00000000);
181
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);
187
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);
194
195         return 0;
196 }
197
198 /* detect_used_resource - subtract resource under dev from bridge */
199 static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *dev)
200 {
201         int count;
202
203         dbg("Device %s\n", pci_name(dev));
204
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;
211
212                 if (!flags)
213                         continue;
214
215                 dbg("BAR[%d] 0x%lx - 0x%lx (0x%lx)\n", count, base,
216                                 base + len - 1, flags);
217
218                 if (flags & IORESOURCE_IO) {
219                         head = &bridge->io_head;
220                 } else if (flags & IORESOURCE_PREFETCH) {
221                         head = &bridge->p_mem_head;
222                 } else {
223                         head = &bridge->mem_head;
224                 }
225
226                 spin_lock(&bridge->res_lock);
227                 res = acpiphp_get_resource_with_base(head, base, len);
228                 spin_unlock(&bridge->res_lock);
229                 if (res)
230                         kfree(res);
231         }
232
233         return 0;
234 }
235
236
237 /**
238  * acpiphp_detect_pci_resource - detect resources under bridge
239  * @bridge: detect all resources already used under this bridge
240  *
241  * collect all resources already allocated for all devices under a bridge.
242  */
243 int acpiphp_detect_pci_resource (struct acpiphp_bridge *bridge)
244 {
245         struct list_head *l;
246         struct pci_dev *dev;
247
248         list_for_each (l, &bridge->pci_bus->devices) {
249                 dev = pci_dev_b(l);
250                 detect_used_resource(bridge, dev);
251         }
252
253         return 0;
254 }
255
256
257 /**
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
260  *
261  * TBD: PCI-to-PCI bridge case
262  *      use pci_dev->resource[]
263  */
264 int acpiphp_init_func_resource (struct acpiphp_func *func)
265 {
266         u64 base;
267         u32 bar, len;
268         u32 address[] = {
269                 PCI_BASE_ADDRESS_0,
270                 PCI_BASE_ADDRESS_1,
271                 PCI_BASE_ADDRESS_2,
272                 PCI_BASE_ADDRESS_3,
273                 PCI_BASE_ADDRESS_4,
274                 PCI_BASE_ADDRESS_5,
275                 0
276         };
277         int count;
278         struct pci_resource *res;
279         struct pci_dev *dev;
280
281         dev = func->pci_dev;
282         dbg("Hot-pluggable device %s\n", pci_name(dev));
283
284         for (count = 0; address[count]; count++) {      /* for 6 BARs */
285                 pci_read_config_dword(dev, address[count], &bar);
286
287                 if (!bar)       /* This BAR is not implemented */
288                         continue;
289
290                 pci_write_config_dword(dev, address[count], 0xFFFFFFFF);
291                 pci_read_config_dword(dev, address[count], &len);
292
293                 if (len & PCI_BASE_ADDRESS_SPACE_IO) {
294                         /* This is IO */
295                         base = bar & 0xFFFFFFFC;
296                         len = len & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF);
297                         len = len & ~(len - 1);
298
299                         dbg("BAR[%d] %08x - %08x (IO)\n", count, (u32)base, (u32)base + len - 1);
300
301                         res = acpiphp_make_resource(base, len);
302                         if (!res)
303                                 goto no_memory;
304
305                         res->next = func->io_head;
306                         func->io_head = res;
307
308                 } else {
309                         /* This is Memory */
310                         base = bar & 0xFFFFFFF0;
311                         if (len & PCI_BASE_ADDRESS_MEM_PREFETCH) {
312                                 /* pfmem */
313
314                                 len &= 0xFFFFFFF0;
315                                 len = ~len + 1;
316
317                                 if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {       /* takes up another dword */
318                                         dbg("prefetch mem 64\n");
319                                         count += 1;
320                                 }
321                                 dbg("BAR[%d] %08x - %08x (PMEM)\n", count, (u32)base, (u32)base + len - 1);
322                                 res = acpiphp_make_resource(base, len);
323                                 if (!res)
324                                         goto no_memory;
325
326                                 res->next = func->p_mem_head;
327                                 func->p_mem_head = res;
328
329                         } else {
330                                 /* regular memory */
331
332                                 len &= 0xFFFFFFF0;
333                                 len = ~len + 1;
334
335                                 if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {
336                                         /* takes up another dword */
337                                         dbg("mem 64\n");
338                                         count += 1;
339                                 }
340                                 dbg("BAR[%d] %08x - %08x (MEM)\n", count, (u32)base, (u32)base + len - 1);
341                                 res = acpiphp_make_resource(base, len);
342                                 if (!res)
343                                         goto no_memory;
344
345                                 res->next = func->mem_head;
346                                 func->mem_head = res;
347
348                         }
349                 }
350
351                 pci_write_config_dword(dev, address[count], bar);
352         }
353 #if 1
354         acpiphp_dump_func_resource(func);
355 #endif
356
357         return 0;
358
359  no_memory:
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);
364
365         return -1;
366 }
367
368
369 /**
370  * acpiphp_configure_slot - allocate PCI resources
371  * @slot: slot to be configured
372  *
373  * initializes a PCI functions on a device inserted
374  * into the slot
375  *
376  */
377 int acpiphp_configure_slot (struct acpiphp_slot *slot)
378 {
379         struct acpiphp_func *func;
380         struct list_head *l;
381         u8 hdr;
382         u32 dvid;
383         int retval = 0;
384         int is_multi = 0;
385
386         pci_bus_read_config_byte(slot->bridge->pci_bus,
387                                  PCI_DEVFN(slot->device, 0),
388                                  PCI_HEADER_TYPE, &hdr);
389
390         if (hdr & 0x80)
391                 is_multi = 1;
392
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,
398                                                             func->function),
399                                                   PCI_VENDOR_ID, &dvid);
400                         if (dvid != 0xffffffff) {
401                                 retval = init_config_space(func);
402                                 if (retval)
403                                         break;
404                         }
405                 }
406         }
407
408         return retval;
409 }
410
411 /**
412  * acpiphp_configure_function - configure PCI function
413  * @func: function to be configured
414  *
415  * initializes a PCI functions on a device inserted
416  * into the slot
417  *
418  */
419 int acpiphp_configure_function (struct acpiphp_func *func)
420 {
421         /* all handled by the pci core now */
422         return 0;
423 }
424
425 /**
426  * acpiphp_unconfigure_function - unconfigure PCI function
427  * @func: function to be unconfigured
428  *
429  */
430 void acpiphp_unconfigure_function (struct acpiphp_func *func)
431 {
432         struct acpiphp_bridge *bridge;
433
434         /* if pci_dev is NULL, ignore it */
435         if (!func->pci_dev)
436                 return;
437
438         pci_remove_bus_device(func->pci_dev);
439
440         /* free all resources */
441         bridge = func->slot->bridge;
442
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);
449 }