patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / drivers / pci / hotplug / cpci_hotplug_pci.c
1 /*
2  * CompactPCI Hot Plug Driver PCI functions
3  *
4  * Copyright (C) 2002 by SOMA Networks, Inc.
5  *
6  * All rights reserved.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or (at
11  * your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
16  * NON INFRINGEMENT.  See the GNU General Public License for more
17  * details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  *
23  * Send feedback to <scottm@somanetworks.com>
24  */
25
26 #include <linux/config.h>
27 #include <linux/module.h>
28 #include <linux/kernel.h>
29 #include <linux/pci.h>
30 #include <linux/proc_fs.h>
31 #include "../pci.h"
32 #include "pci_hotplug.h"
33 #include "cpci_hotplug.h"
34
35 #if !defined(CONFIG_HOTPLUG_CPCI_MODULE)
36 #define MY_NAME "cpci_hotplug"
37 #else
38 #define MY_NAME THIS_MODULE->name
39 #endif
40
41 extern int cpci_debug;
42
43 #define dbg(format, arg...)                                     \
44         do {                                                    \
45                 if(cpci_debug)                                  \
46                         printk (KERN_DEBUG "%s: " format "\n",  \
47                                 MY_NAME , ## arg);              \
48         } while(0)
49 #define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
50 #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
51 #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
52
53 #define ROUND_UP(x, a)          (((x) + (a) - 1) & ~((a) - 1))
54
55
56 u8 cpci_get_attention_status(struct slot* slot)
57 {
58         int hs_cap;
59         u16 hs_csr;
60
61         hs_cap = pci_bus_find_capability(slot->bus,
62                                          slot->devfn,
63                                          PCI_CAP_ID_CHSWP);
64         if(!hs_cap) {
65                 return 0;
66         }
67
68         if(pci_bus_read_config_word(slot->bus,
69                                      slot->devfn,
70                                      hs_cap + 2,
71                                      &hs_csr)) {
72                 return 0;
73         }
74         return hs_csr & 0x0008 ? 1 : 0;
75 }
76
77 int cpci_set_attention_status(struct slot* slot, int status)
78 {
79         int hs_cap;
80         u16 hs_csr;
81
82         hs_cap = pci_bus_find_capability(slot->bus,
83                                          slot->devfn,
84                                          PCI_CAP_ID_CHSWP);
85         if(!hs_cap) {
86                 return 0;
87         }
88
89         if(pci_bus_read_config_word(slot->bus,
90                                      slot->devfn,
91                                      hs_cap + 2,
92                                      &hs_csr)) {
93                 return 0;
94         }
95         if(status) {
96                 hs_csr |= HS_CSR_LOO;
97         } else {
98                 hs_csr &= ~HS_CSR_LOO;
99         }
100         if(pci_bus_write_config_word(slot->bus,
101                                       slot->devfn,
102                                       hs_cap + 2,
103                                       hs_csr)) {
104                 return 0;
105         }
106         return 1;
107 }
108
109 u16 cpci_get_hs_csr(struct slot* slot)
110 {
111         int hs_cap;
112         u16 hs_csr;
113
114         hs_cap = pci_bus_find_capability(slot->bus,
115                                          slot->devfn,
116                                          PCI_CAP_ID_CHSWP);
117         if(!hs_cap) {
118                 return 0xFFFF;
119         }
120
121         if(pci_bus_read_config_word(slot->bus,
122                                      slot->devfn,
123                                      hs_cap + 2,
124                                      &hs_csr)) {
125                 return 0xFFFF;
126         }
127         return hs_csr;
128 }
129
130 #if 0
131 u16 cpci_set_hs_csr(struct slot* slot, u16 hs_csr)
132 {
133         int hs_cap;
134         u16 new_hs_csr;
135
136         hs_cap = pci_bus_find_capability(slot->bus,
137                                          slot->devfn,
138                                          PCI_CAP_ID_CHSWP);
139         if(!hs_cap) {
140                 return 0xFFFF;
141         }
142
143         /* Write out the new value */
144         if(pci_bus_write_config_word(slot->bus,
145                                       slot->devfn,
146                                       hs_cap + 2,
147                                       hs_csr)) {
148                 return 0xFFFF;
149         }
150
151         /* Read back what we just wrote out */
152         if(pci_bus_read_config_word(slot->bus,
153                                      slot->devfn,
154                                      hs_cap + 2,
155                                      &new_hs_csr)) {
156                 return 0xFFFF;
157         }
158         return new_hs_csr;
159 }
160 #endif
161
162 int cpci_check_and_clear_ins(struct slot* slot)
163 {
164         int hs_cap;
165         u16 hs_csr;
166         int ins = 0;
167
168         hs_cap = pci_bus_find_capability(slot->bus,
169                                          slot->devfn,
170                                          PCI_CAP_ID_CHSWP);
171         if(!hs_cap) {
172                 return 0;
173         }
174         if(pci_bus_read_config_word(slot->bus,
175                                      slot->devfn,
176                                      hs_cap + 2,
177                                      &hs_csr)) {
178                 return 0;
179         }
180         if(hs_csr & HS_CSR_INS) {
181                 /* Clear INS (by setting it) */
182                 if(pci_bus_write_config_word(slot->bus,
183                                               slot->devfn,
184                                               hs_cap + 2,
185                                               hs_csr)) {
186                         ins = 0;
187                 }
188                 ins = 1;
189         }
190         return ins;
191 }
192
193 int cpci_check_ext(struct slot* slot)
194 {
195         int hs_cap;
196         u16 hs_csr;
197         int ext = 0;
198
199         hs_cap = pci_bus_find_capability(slot->bus,
200                                          slot->devfn,
201                                          PCI_CAP_ID_CHSWP);
202         if(!hs_cap) {
203                 return 0;
204         }
205         if(pci_bus_read_config_word(slot->bus,
206                                      slot->devfn,
207                                      hs_cap + 2,
208                                      &hs_csr)) {
209                 return 0;
210         }
211         if(hs_csr & HS_CSR_EXT) {
212                 ext = 1;
213         }
214         return ext;
215 }
216
217 int cpci_clear_ext(struct slot* slot)
218 {
219         int hs_cap;
220         u16 hs_csr;
221
222         hs_cap = pci_bus_find_capability(slot->bus,
223                                          slot->devfn,
224                                          PCI_CAP_ID_CHSWP);
225         if(!hs_cap) {
226                 return -ENODEV;
227         }
228         if(pci_bus_read_config_word(slot->bus,
229                                      slot->devfn,
230                                      hs_cap + 2,
231                                      &hs_csr)) {
232                 return -ENODEV;
233         }
234         if(hs_csr & HS_CSR_EXT) {
235                 /* Clear EXT (by setting it) */
236                 if(pci_bus_write_config_word(slot->bus,
237                                               slot->devfn,
238                                               hs_cap + 2,
239                                               hs_csr)) {
240                         return -ENODEV;
241                 }
242         }
243         return 0;
244 }
245
246 int cpci_led_on(struct slot* slot)
247 {
248         int hs_cap;
249         u16 hs_csr;
250
251         hs_cap = pci_bus_find_capability(slot->bus,
252                                          slot->devfn,
253                                          PCI_CAP_ID_CHSWP);
254         if(!hs_cap) {
255                 return -ENODEV;
256         }
257         if(pci_bus_read_config_word(slot->bus,
258                                      slot->devfn,
259                                      hs_cap + 2,
260                                      &hs_csr)) {
261                 return -ENODEV;
262         }
263         if((hs_csr & HS_CSR_LOO) != HS_CSR_LOO) {
264                 /* Set LOO */
265                 hs_csr |= HS_CSR_LOO;
266                 if(pci_bus_write_config_word(slot->bus,
267                                               slot->devfn,
268                                               hs_cap + 2,
269                                               hs_csr)) {
270                         err("Could not set LOO for slot %s",
271                             slot->hotplug_slot->name);
272                         return -ENODEV;
273                 }
274         }
275         return 0;
276 }
277
278 int cpci_led_off(struct slot* slot)
279 {
280         int hs_cap;
281         u16 hs_csr;
282
283         hs_cap = pci_bus_find_capability(slot->bus,
284                                          slot->devfn,
285                                          PCI_CAP_ID_CHSWP);
286         if(!hs_cap) {
287                 return -ENODEV;
288         }
289         if(pci_bus_read_config_word(slot->bus,
290                                      slot->devfn,
291                                      hs_cap + 2,
292                                      &hs_csr)) {
293                 return -ENODEV;
294         }
295         if(hs_csr & HS_CSR_LOO) {
296                 /* Clear LOO */
297                 hs_csr &= ~HS_CSR_LOO;
298                 if(pci_bus_write_config_word(slot->bus,
299                                               slot->devfn,
300                                               hs_cap + 2,
301                                               hs_csr)) {
302                         err("Could not clear LOO for slot %s",
303                             slot->hotplug_slot->name);
304                         return -ENODEV;
305                 }
306         }
307         return 0;
308 }
309
310
311 /*
312  * Device configuration functions
313  */
314
315 static int cpci_configure_dev(struct pci_bus *bus, struct pci_dev *dev)
316 {
317         u8 irq_pin;
318         int r;
319
320         dbg("%s - enter", __FUNCTION__);
321
322         /* NOTE: device already setup from prior scan */
323
324         /* FIXME: How would we know if we need to enable the expansion ROM? */
325         pci_write_config_word(dev, PCI_ROM_ADDRESS, 0x00L);
326
327         /* Assign resources */
328         dbg("assigning resources for %02x:%02x.%x",
329             dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
330         for (r = 0; r < 6; r++) {
331                 struct resource *res = dev->resource + r;
332                 if(res->flags)
333                         pci_assign_resource(dev, r);
334         }
335         dbg("finished assigning resources for %02x:%02x.%x",
336             dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
337
338         /* Does this function have an interrupt at all? */
339         dbg("checking for function interrupt");
340         pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq_pin);
341         if(irq_pin) {
342                 dbg("function uses interrupt pin %d", irq_pin);
343         }
344
345         /*
346          * Need to explicitly set irq field to 0 so that it'll get assigned
347          * by the pcibios platform dependent code called by pci_enable_device.
348          */
349         dev->irq = 0;
350
351         dbg("enabling device");
352         pci_enable_device(dev); /* XXX check return */
353         dbg("now dev->irq = %d", dev->irq);
354         if(irq_pin && dev->irq) {
355                 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
356         }
357
358         /* Can't use pci_insert_device at the moment, do it manually for now */
359         pci_proc_attach_device(dev);
360         dbg("notifying drivers");
361         //pci_announce_device_to_drivers(dev);
362         dbg("%s - exit", __FUNCTION__);
363         return 0;
364 }
365
366 static int cpci_configure_bridge(struct pci_bus* bus, struct pci_dev* dev)
367 {
368         int rc;
369         struct pci_bus* child;
370         struct resource* r;
371         u8 max, n;
372         u16 command;
373
374         dbg("%s - enter", __FUNCTION__);
375
376         /* Do basic bridge initialization */
377         rc = pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x40);
378         if(rc) {
379                 printk(KERN_ERR "%s - write of PCI_LATENCY_TIMER failed\n", __FUNCTION__);
380         }
381         rc = pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 0x40);
382         if(rc) {
383                 printk(KERN_ERR "%s - write of PCI_SEC_LATENCY_TIMER failed\n", __FUNCTION__);
384         }
385         rc = pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES / 4);
386         if(rc) {
387                 printk(KERN_ERR "%s - write of PCI_CACHE_LINE_SIZE failed\n", __FUNCTION__);
388         }
389
390         /*
391          * Set parent bridge's subordinate field so that configuration space
392          * access will work in pci_scan_bridge and friends.
393          */
394         max = pci_max_busnr();
395         bus->subordinate = max + 1;
396         pci_write_config_byte(bus->self, PCI_SUBORDINATE_BUS, max + 1);
397
398         /* Scan behind bridge */
399         n = pci_scan_bridge(bus, dev, max, 2);
400         child = pci_find_bus(0, max + 1);
401         if (!child)
402                 return -ENODEV;
403         pci_proc_attach_bus(child);
404
405         /*
406          * Update parent bridge's subordinate field if there were more bridges
407          * behind the bridge that was scanned.
408          */
409         if(n > max) {
410                 bus->subordinate = n;
411                 pci_write_config_byte(bus->self, PCI_SUBORDINATE_BUS, n);
412         }
413
414         /*
415          * Update the bridge resources of the bridge to accommodate devices
416          * behind it.
417          */
418         pci_bus_size_bridges(child);
419         pci_bus_assign_resources(child);
420
421         /* Enable resource mapping via command register */
422         command = PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
423         r = child->resource[0];
424         if(r && r->start) {
425                 command |= PCI_COMMAND_IO;
426         }
427         r = child->resource[1];
428         if(r && r->start) {
429                 command |= PCI_COMMAND_MEMORY;
430         }
431         r = child->resource[2];
432         if(r && r->start) {
433                 command |= PCI_COMMAND_MEMORY;
434         }
435         rc = pci_write_config_word(dev, PCI_COMMAND, command);
436         if(rc) {
437                 err("Error setting command register");
438                 return rc;
439         }
440
441         /* Set bridge control register */
442         command = PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR | PCI_BRIDGE_CTL_NO_ISA;
443         rc = pci_write_config_word(dev, PCI_BRIDGE_CONTROL, command);
444         if(rc) {
445                 err("Error setting bridge control register");
446                 return rc;
447         }
448         dbg("%s - exit", __FUNCTION__);
449         return 0;
450 }
451
452 static int configure_visit_pci_dev(struct pci_dev_wrapped *wrapped_dev,
453                                    struct pci_bus_wrapped *wrapped_bus)
454 {
455         int rc;
456         struct pci_dev *dev = wrapped_dev->dev;
457         struct pci_bus *bus = wrapped_bus->bus;
458         struct slot* slot;
459
460         dbg("%s - enter", __FUNCTION__);
461
462         /*
463          * We need to fix up the hotplug representation with the Linux
464          * representation.
465          */
466         if(wrapped_dev->data) {
467                 slot = (struct slot*) wrapped_dev->data;
468                 slot->dev = dev;
469         }
470
471         /* If it's a bridge, scan behind it for devices */
472         if(dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
473                 rc = cpci_configure_bridge(bus, dev);
474                 if(rc)
475                         return rc;
476         }
477
478         /* Actually configure device */
479         if(dev) {
480                 rc = cpci_configure_dev(bus, dev);
481                 if(rc)
482                         return rc;
483         }
484         dbg("%s - exit", __FUNCTION__);
485         return 0;
486 }
487
488 static int unconfigure_visit_pci_dev_phase2(struct pci_dev_wrapped *wrapped_dev,
489                                             struct pci_bus_wrapped *wrapped_bus)
490 {
491         struct pci_dev *dev = wrapped_dev->dev;
492         struct slot* slot;
493
494         dbg("%s - enter", __FUNCTION__);
495         if(!dev)
496                 return -ENODEV;
497
498         /* Remove the Linux representation */
499         if(pci_remove_device_safe(dev)) {
500                 err("Could not remove device\n");
501                 return -1;
502         }
503
504         /*
505          * Now remove the hotplug representation.
506          */
507         if(wrapped_dev->data) {
508                 slot = (struct slot*) wrapped_dev->data;
509                 slot->dev = NULL;
510         } else {
511                 dbg("No hotplug representation for %02x:%02x.%x",
512                     dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
513         }
514         dbg("%s - exit", __FUNCTION__);
515         return 0;
516 }
517
518 static int unconfigure_visit_pci_bus_phase2(struct pci_bus_wrapped *wrapped_bus,
519                                             struct pci_dev_wrapped *wrapped_dev)
520 {
521         struct pci_bus *bus = wrapped_bus->bus;
522         struct pci_bus *parent = bus->self->bus;
523
524         dbg("%s - enter", __FUNCTION__);
525
526         /* The cleanup code for proc entries regarding buses should be in the kernel... */
527         if(bus->procdir)
528                 dbg("detach_pci_bus %s", bus->procdir->name);
529         pci_proc_detach_bus(bus);
530
531         /* The cleanup code should live in the kernel... */
532         bus->self->subordinate = NULL;
533
534         /* unlink from parent bus */
535         list_del(&bus->node);
536
537         /* Now, remove */
538         if(bus)
539                 kfree(bus);
540
541         /* Update parent's subordinate field */
542         if(parent) {
543                 u8 n = pci_bus_max_busnr(parent);
544                 if(n < parent->subordinate) {
545                         parent->subordinate = n;
546                         pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS, n);
547                 }
548         }
549         dbg("%s - exit", __FUNCTION__);
550         return 0;
551 }
552
553 static struct pci_visit configure_functions = {
554         .visit_pci_dev = configure_visit_pci_dev,
555 };
556
557 static struct pci_visit unconfigure_functions_phase2 = {
558         .post_visit_pci_bus = unconfigure_visit_pci_bus_phase2,
559         .post_visit_pci_dev = unconfigure_visit_pci_dev_phase2
560 };
561
562
563 int cpci_configure_slot(struct slot* slot)
564 {
565         int rc = 0;
566
567         dbg("%s - enter", __FUNCTION__);
568
569         if(slot->dev == NULL) {
570                 dbg("pci_dev null, finding %02x:%02x:%x",
571                     slot->bus->number, PCI_SLOT(slot->devfn), PCI_FUNC(slot->devfn));
572                 slot->dev = pci_find_slot(slot->bus->number, slot->devfn);
573         }
574
575         /* Still NULL? Well then scan for it! */
576         if(slot->dev == NULL) {
577                 int n;
578                 dbg("pci_dev still null");
579
580                 /*
581                  * This will generate pci_dev structures for all functions, but
582                  * we will only call this case when lookup fails.
583                  */
584                 n = pci_scan_slot(slot->bus, slot->devfn);
585                 dbg("%s: pci_scan_slot returned %d", __FUNCTION__, n);
586                 if(n > 0)
587                         pci_bus_add_devices(slot->bus);
588                 slot->dev = pci_find_slot(slot->bus->number, slot->devfn);
589                 if(slot->dev == NULL) {
590                         err("Could not find PCI device for slot %02x", slot->number);
591                         return 0;
592                 }
593         }
594         dbg("slot->dev = %p", slot->dev);
595         if(slot->dev) {
596                 struct pci_dev *dev;
597                 struct pci_dev_wrapped wrapped_dev;
598                 struct pci_bus_wrapped wrapped_bus;
599                 int i;
600
601                 memset(&wrapped_dev, 0, sizeof (struct pci_dev_wrapped));
602                 memset(&wrapped_bus, 0, sizeof (struct pci_bus_wrapped));
603
604                 for (i = 0; i < 8; i++) {
605                         dev = pci_find_slot(slot->bus->number,
606                                             PCI_DEVFN(PCI_SLOT(slot->dev->devfn), i));
607                         if(!dev)
608                                 continue;
609                         wrapped_dev.dev = dev;
610                         wrapped_bus.bus = slot->dev->bus;
611                         if(i)
612                                 wrapped_dev.data = NULL;
613                         else
614                                 wrapped_dev.data = (void*) slot;
615                         rc = pci_visit_dev(&configure_functions, &wrapped_dev, &wrapped_bus);
616                 }
617         }
618
619         dbg("%s - exit, rc = %d", __FUNCTION__, rc);
620         return rc;
621 }
622
623 int cpci_unconfigure_slot(struct slot* slot)
624 {
625         int rc = 0;
626         int i;
627         struct pci_dev_wrapped wrapped_dev;
628         struct pci_bus_wrapped wrapped_bus;
629         struct pci_dev *dev;
630
631         dbg("%s - enter", __FUNCTION__);
632
633         if(!slot->dev) {
634                 err("No device for slot %02x\n", slot->number);
635                 return -ENODEV;
636         }
637
638         memset(&wrapped_dev, 0, sizeof (struct pci_dev_wrapped));
639         memset(&wrapped_bus, 0, sizeof (struct pci_bus_wrapped));
640
641         for (i = 0; i < 8; i++) {
642                 dev = pci_find_slot(slot->bus->number,
643                                     PCI_DEVFN(PCI_SLOT(slot->devfn), i));
644                 if(dev) {
645                         wrapped_dev.dev = dev;
646                         wrapped_bus.bus = dev->bus;
647                         if(i)
648                                 wrapped_dev.data = NULL;
649                         else
650                                 wrapped_dev.data = (void*) slot;
651                         dbg("%s - unconfigure phase 2", __FUNCTION__);
652                         rc = pci_visit_dev(&unconfigure_functions_phase2,
653                                            &wrapped_dev,
654                                            &wrapped_bus);
655                         if(rc)
656                                 break;
657                 }
658         }
659         dbg("%s - exit, rc = %d", __FUNCTION__, rc);
660         return rc;
661 }