Annotation of Gnu-Mach/linux/src/drivers/net/pci-scan.c, revision 1.1.1.2

1.1       root        1: /* pci-scan.c: Linux PCI network adapter support code. */
                      2: /*
                      3:        Originally written 1999-2003 by Donald Becker.
                      4: 
                      5:        This software may be used and distributed according to the terms
                      6:        of the GNU General Public License (GPL), incorporated herein by
                      7:        reference.  Drivers interacting with these functions are derivative
                      8:        works and thus also must be licensed under the GPL and include an explicit
                      9:        GPL notice.
                     10: 
                     11:        This code provides common scan and activate functions for PCI network
                     12:        interfaces.
                     13: 
                     14:        The author may be reached as [email protected], or
                     15:        Donald Becker
                     16:        Scyld Computing Corporation
                     17:        914 Bay Ridge Road, Suite 220
                     18:        Annapolis MD 21403
                     19: 
                     20:        Other contributers:
                     21: */
                     22: static const char version[] =
                     23: "pci-scan.c:v1.12 7/30/2003  Donald Becker <[email protected]>"
                     24: " http://www.scyld.com/linux/drivers.html\n";
                     25: 
                     26: /* A few user-configurable values that may be modified when a module. */
                     27: 
                     28: static int msg_level = 1;              /* 1 normal messages, 0 quiet .. 7 verbose. */
                     29: static int min_pci_latency = 32;
                     30: 
                     31: #if ! defined(__KERNEL__)
                     32: #define __KERNEL__ 1
                     33: #endif
1.1.1.2 ! root       34: #if !defined(__OPTIMIZE__) && /* Mach glue, we think this is ok now: */ 0
1.1       root       35: #warning  You must compile this file with the correct options!
                     36: #warning  See the last lines of the source file.
                     37: #error You must compile this driver with the proper options, including "-O".
                     38: #endif
                     39: 
                     40: #if defined(MODULE) && ! defined(EXPORT_SYMTAB)
                     41: #define EXPORT_SYMTAB
                     42: #endif
                     43: 
                     44: #include <linux/config.h>
                     45: #if defined(CONFIG_SMP) && ! defined(__SMP__)
                     46: #define __SMP__
                     47: #endif
                     48: #if defined(MODULE) && defined(CONFIG_MODVERSIONS) && ! defined(MODVERSIONS)
                     49: #define MODVERSIONS
                     50: #endif
                     51: 
                     52: #include <linux/version.h>
                     53: #if defined(MODVERSIONS)
                     54: #include <linux/modversions.h>
                     55: #endif
                     56: #if LINUX_VERSION_CODE < 0x20500  &&  defined(MODVERSIONS)
                     57: /* Another interface semantics screw-up. */
                     58: #include <linux/module.h>
                     59: #include <linux/modversions.h>
                     60: #else
                     61: #include <linux/module.h>
                     62: #endif
                     63: 
                     64: #include <linux/kernel.h>
                     65: #include <linux/mm.h>
                     66: #include <linux/errno.h>
                     67: #include <linux/types.h>
                     68: #include <linux/pci.h>
                     69: #include <linux/ioport.h>
                     70: #if LINUX_VERSION_CODE >= 0x20300
                     71: /* Bogus change in the middle of a "stable" kernel series.
                     72:    Also, in 2.4.7+ slab must come before interrupt.h to avoid breakage. */
                     73: #include <linux/slab.h>
                     74: #else
                     75: #include <linux/malloc.h>
                     76: #endif
                     77: #include <asm/io.h>
                     78: #include "pci-scan.h"
                     79: #include "kern_compat.h"
                     80: #if defined(CONFIG_APM)  &&  LINUX_VERSION_CODE < 0x20400 
                     81: #include <linux/apm_bios.h>
                     82: #endif
                     83: #ifdef CONFIG_PM
                     84: /* New in 2.4 kernels, pointlessly incompatible with earlier APM. */
                     85: #include <linux/pm.h>
                     86: #endif
                     87: 
                     88: #if (LINUX_VERSION_CODE >= 0x20100) && defined(MODULE)
                     89: char kernel_version[] = UTS_RELEASE;
                     90: #endif
                     91: #if (LINUX_VERSION_CODE < 0x20100)
                     92: #define PCI_CAPABILITY_LIST    0x34    /* Offset of first capability list entry */
                     93: #define PCI_STATUS_CAP_LIST    0x10    /* Support Capability List */
                     94: #define PCI_CAP_ID_PM          0x01    /* Power Management */
                     95: #endif
                     96: 
                     97: int (*register_hotswap_hook)(struct drv_id_info *did);
                     98: void (*unregister_hotswap_hook)(struct drv_id_info *did);
                     99: 
                    100: #if LINUX_VERSION_CODE > 0x20118  &&  defined(MODULE)
                    101: MODULE_LICENSE("GPL");
                    102: MODULE_PARM(msg_level, "i");
                    103: MODULE_PARM(min_pci_latency, "i");
                    104: MODULE_PARM_DESC(msg_level, "Enable additional status messages (0-7)");
                    105: MODULE_PARM_DESC(min_pci_latency,
                    106:                                 "Minimum value for the PCI Latency Timer settings");
                    107: #if defined(EXPORT_SYMTAB)
                    108: EXPORT_SYMBOL_NOVERS(pci_drv_register);
                    109: EXPORT_SYMBOL_NOVERS(pci_drv_unregister);
                    110: EXPORT_SYMBOL_NOVERS(acpi_wake);
                    111: EXPORT_SYMBOL_NOVERS(acpi_set_pwr_state);
                    112: EXPORT_SYMBOL_NOVERS(register_hotswap_hook);
                    113: EXPORT_SYMBOL_NOVERS(unregister_hotswap_hook);
                    114: #endif
                    115: #endif
                    116: 
                    117: /* List of registered drivers. */
                    118: static struct drv_id_info *drv_list;
                    119: /* List of detected PCI devices, for APM events. */
                    120: static struct dev_info {
                    121:        struct dev_info *next;
                    122:        void *dev;
                    123:        struct drv_id_info *drv_id;
                    124:        int flags;
                    125: } *dev_list;
                    126: 
                    127: /*
                    128:   This code is not intended to support every configuration.
                    129:   It is intended to minimize duplicated code by providing the functions
                    130:   needed in almost every PCI driver.
                    131: 
                    132:   The "no kitchen sink" policy:
                    133:   Additional features and code will be added to this module only if more
                    134:   than half of the drivers for common hardware would benefit from the feature.
                    135: */
                    136: 
                    137: /*
                    138:   Ideally we would detect and number all cards of a type (e.g. network) in
                    139:   PCI slot order.
                    140:   But that does not work with hot-swap card, CardBus cards and added drivers.
                    141:   So instead we detect just the each chip table in slot order.
                    142: 
                    143:   This routine takes a PCI ID table, scans the PCI bus, and calls the
                    144:   associated attach/probe1 routine with the hardware already activated and
                    145:   single I/O or memory address already mapped.
                    146: 
                    147:   This routine will later be supplemented with CardBus and hot-swap PCI
                    148:   support using the same table.  Thus the pci_chip_tbl[] should not be
                    149:   marked as __initdata.
                    150: */
                    151: 
                    152: #if LINUX_VERSION_CODE >= 0x20200
                    153: /* Grrrr.. complex abstaction layers with negative benefit. */
                    154: int pci_drv_register(struct drv_id_info *drv_id, void *initial_device)
                    155: {
                    156:        int chip_idx, cards_found = 0;
                    157:        struct pci_dev *pdev = NULL;
                    158:        struct pci_id_info *pci_tbl = drv_id->pci_dev_tbl;
                    159:        struct drv_id_info *drv;
                    160:        void *newdev;
                    161: 
                    162: 
                    163:        /* Ignore a double-register attempt. */
                    164:        for (drv = drv_list; drv; drv = drv->next)
                    165:                if (drv == drv_id)
                    166:                        return -EBUSY;
                    167: 
                    168:        while ((pdev = pci_find_class(drv_id->pci_class, pdev)) != 0) {
                    169:                u32 pci_id, pci_subsys_id, pci_class_rev;
                    170:                u16 pci_command, new_command;
                    171:                int pci_flags;
                    172:                long pciaddr;                   /* Bus address. */
                    173:                long ioaddr;                    /* Mapped address for this processor. */
                    174: 
                    175:                pci_read_config_dword(pdev, PCI_VENDOR_ID, &pci_id);
                    176:                /* Offset 0x2c is PCI_SUBSYSTEM_ID aka PCI_SUBSYSTEM_VENDOR_ID. */
                    177:                pci_read_config_dword(pdev, 0x2c, &pci_subsys_id);
                    178:                pci_read_config_dword(pdev, PCI_REVISION_ID, &pci_class_rev);
                    179: 
                    180:                if (msg_level > 3)
                    181:                        printk(KERN_DEBUG "PCI ID %8.8x subsystem ID is %8.8x.\n",
                    182:                                   pci_id, pci_subsys_id);
                    183:                for (chip_idx = 0; pci_tbl[chip_idx].name; chip_idx++) {
                    184:                        struct pci_id_info *chip = &pci_tbl[chip_idx];
                    185:                        if ((pci_id & chip->id.pci_mask) == chip->id.pci
                    186:                                && (pci_subsys_id&chip->id.subsystem_mask) == chip->id.subsystem
                    187:                                && (pci_class_rev&chip->id.revision_mask) == chip->id.revision)
                    188:                                break;
                    189:                }
                    190:                if (pci_tbl[chip_idx].name == 0)                /* Compiled out! */
                    191:                        continue;
                    192: 
                    193:                pci_flags = pci_tbl[chip_idx].pci_flags;
                    194: #if LINUX_VERSION_CODE >= 0x2030C
                    195:                /* Wow. A oversized, hard-to-use abstraction. Bogus. */
                    196:                pciaddr = pdev->resource[(pci_flags >> 4) & 7].start;
                    197: #else
                    198:                pciaddr = pdev->base_address[(pci_flags >> 4) & 7];
                    199: #if defined(__alpha__)                 /* Really any machine with 64 bit addressing. */
                    200:                if (pci_flags & PCI_ADDR_64BITS)
                    201:                        pciaddr |= ((long)pdev->base_address[((pci_flags>>4)&7)+ 1]) << 32;
                    202: #endif
                    203: #endif
                    204:                if (msg_level > 2)
                    205:                        printk(KERN_INFO "Found %s at PCI address %#lx, mapped IRQ %d.\n",
                    206:                                   pci_tbl[chip_idx].name, pciaddr, pdev->irq);
                    207: 
                    208:                if ( ! (pci_flags & PCI_UNUSED_IRQ)  &&
                    209:                         (pdev->irq == 0 || pdev->irq == 255)) {
                    210:                        if (pdev->bus->number == 32)    /* Broken CardBus activation. */
                    211:                                printk(KERN_WARNING "Resources for CardBus device '%s' have"
                    212:                                           " not been allocated.\n"
                    213:                                           KERN_WARNING "Activation has been delayed.\n",
                    214:                                           pci_tbl[chip_idx].name);
                    215:                        else
                    216:                                printk(KERN_WARNING "PCI device '%s' was not assigned an "
                    217:                                           "IRQ.\n"
                    218:                                           KERN_WARNING "It will not be activated.\n",
                    219:                                   pci_tbl[chip_idx].name);
                    220:                        continue;
                    221:                }
                    222:                if ((pci_flags & PCI_BASE_ADDRESS_SPACE_IO)) {
                    223:                        ioaddr = pciaddr & PCI_BASE_ADDRESS_IO_MASK;
                    224:                        if (check_region(ioaddr, pci_tbl[chip_idx].io_size))
                    225:                                continue;
                    226:                } else if ((ioaddr = (long)ioremap(pciaddr & PCI_BASE_ADDRESS_MEM_MASK,
                    227:                                                                                   pci_tbl[chip_idx].io_size)) == 0) {
                    228:                        printk(KERN_INFO "Failed to map PCI address %#lx for device "
                    229:                                   "'%s'.\n", pciaddr, pci_tbl[chip_idx].name);
                    230:                        continue;
                    231:                }
                    232:                if ( ! (pci_flags & PCI_NO_ACPI_WAKE))
                    233:                        acpi_wake(pdev);
                    234:                pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
                    235:                new_command = pci_command | (pci_flags & 7);
                    236:                if (pci_command != new_command) {
                    237:                        printk(KERN_INFO "  The PCI BIOS has not enabled the"
                    238:                                   " device at %d/%d!  Updating PCI command %4.4x->%4.4x.\n",
                    239:                                   pdev->bus->number, pdev->devfn, pci_command, new_command);
                    240:                        pci_write_config_word(pdev, PCI_COMMAND, new_command);
                    241:                }
                    242: 
                    243:                newdev = drv_id->probe1(pdev, initial_device,
                    244:                                                                ioaddr, pdev->irq, chip_idx, cards_found);
                    245:                if (newdev == NULL)
                    246:                        continue;
                    247:                initial_device = 0;
                    248:                cards_found++;
                    249:                if (pci_flags & PCI_COMMAND_MASTER) {
                    250:                        pci_set_master(pdev);
                    251:                        if ( ! (pci_flags & PCI_NO_MIN_LATENCY)) {
                    252:                                u8 pci_latency;
                    253:                                pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
                    254:                                if (pci_latency < min_pci_latency) {
                    255:                                        printk(KERN_INFO "  PCI latency timer (CFLT) is "
                    256:                                                   "unreasonably low at %d.  Setting to %d clocks.\n",
                    257:                                                   pci_latency, min_pci_latency);
                    258:                                        pci_write_config_byte(pdev, PCI_LATENCY_TIMER,
                    259:                                                                                  min_pci_latency);
                    260:                                }
                    261:                        }
                    262:                }
                    263:                {
                    264:                        struct dev_info *devp =
                    265:                                kmalloc(sizeof(struct dev_info), GFP_KERNEL);
                    266:                        if (devp == 0)
                    267:                                continue;
                    268:                        devp->next = dev_list;
                    269:                        devp->dev = newdev;
                    270:                        devp->drv_id = drv_id;
                    271:                        dev_list = devp;
                    272:                }
                    273:        }
                    274: 
                    275:        if (((drv_id->flags & PCI_HOTSWAP)
                    276:                 && register_hotswap_hook && (*register_hotswap_hook)(drv_id) == 0)
                    277:                || cards_found) {
                    278:                MOD_INC_USE_COUNT;
                    279:                drv_id->next = drv_list;
                    280:                drv_list = drv_id;
                    281:                return 0;
                    282:        } else
                    283:                return -ENODEV;
                    284: }
                    285: #else
                    286: int pci_drv_register(struct drv_id_info *drv_id, void *initial_device)
                    287: {
                    288:        int pci_index, cards_found = 0;
                    289:        unsigned char pci_bus, pci_device_fn;
                    290:        struct pci_dev *pdev;
                    291:        struct pci_id_info *pci_tbl = drv_id->pci_dev_tbl;
                    292:        void *newdev;
                    293: 
                    294:        if ( ! pcibios_present())
                    295:                return -ENODEV;
                    296: 
                    297:        for (pci_index = 0; pci_index < 0xff; pci_index++) {
                    298:                u32 pci_id, subsys_id, pci_class_rev;
                    299:                u16 pci_command, new_command;
                    300:                int chip_idx, irq, pci_flags;
                    301:                long pciaddr;
                    302:                long ioaddr;
                    303:                u32 pci_busaddr;
                    304:                u8 pci_irq_line;
                    305: 
                    306:                if (pcibios_find_class (drv_id->pci_class, pci_index,
                    307:                                                                &pci_bus, &pci_device_fn)
                    308:                        != PCIBIOS_SUCCESSFUL)
                    309:                        break;
                    310:                pcibios_read_config_dword(pci_bus, pci_device_fn,
                    311:                                                                  PCI_VENDOR_ID, &pci_id);
                    312:                /* Offset 0x2c is PCI_SUBSYSTEM_ID aka PCI_SUBSYSTEM_VENDOR_ID. */
                    313:                pcibios_read_config_dword(pci_bus, pci_device_fn, 0x2c, &subsys_id);
                    314:                pcibios_read_config_dword(pci_bus, pci_device_fn,
                    315:                                                                  PCI_REVISION_ID, &pci_class_rev);
                    316: 
                    317:                for (chip_idx = 0; pci_tbl[chip_idx].name; chip_idx++) {
                    318:                        struct pci_id_info *chip = &pci_tbl[chip_idx];
                    319:                        if ((pci_id & chip->id.pci_mask) == chip->id.pci
                    320:                                && (subsys_id & chip->id.subsystem_mask) == chip->id.subsystem
                    321:                                && (pci_class_rev&chip->id.revision_mask) == chip->id.revision)
                    322:                                break;
                    323:                }
                    324:                if (pci_tbl[chip_idx].name == 0)                /* Compiled out! */
                    325:                        continue;
                    326: 
                    327:                pci_flags = pci_tbl[chip_idx].pci_flags;
                    328:                pdev = pci_find_slot(pci_bus, pci_device_fn);
                    329:                pcibios_read_config_byte(pci_bus, pci_device_fn,
                    330:                                                                 PCI_INTERRUPT_LINE, &pci_irq_line);
                    331:                irq = pci_irq_line;
                    332:                pcibios_read_config_dword(pci_bus, pci_device_fn,
                    333:                                                                  ((pci_flags >> 2) & 0x1C) + 0x10,
                    334:                                                                  &pci_busaddr);
                    335:                pciaddr = pci_busaddr;
                    336: #if defined(__alpha__)
                    337:                if (pci_flags & PCI_ADDR_64BITS) {
                    338:                        pcibios_read_config_dword(pci_bus, pci_device_fn,
                    339:                                                                          ((pci_flags >> 2) & 0x1C) + 0x14,
                    340:                                                                          &pci_busaddr);
                    341:                        pciaddr |= ((long)pci_busaddr)<<32;
                    342:                }
                    343: #endif
                    344: 
                    345:                if (msg_level > 2)
                    346:                        printk(KERN_INFO "Found %s at PCI address %#lx, IRQ %d.\n",
                    347:                                   pci_tbl[chip_idx].name, pciaddr, irq);
                    348: 
                    349:                if ( ! (pci_flags & PCI_UNUSED_IRQ)  &&
                    350:                         (irq == 0 || irq >= 16)) {
                    351:                        if (pci_bus == 32)      /* Broken CardBus activation. */
                    352:                                printk(KERN_WARNING "Resources for CardBus device '%s' have"
                    353:                                           " not been allocated.\n"
                    354:                                           KERN_WARNING "It will not be activated.\n",
                    355:                                           pci_tbl[chip_idx].name);
                    356:                        else
                    357:                                printk(KERN_WARNING "PCI device '%s' was not assigned an "
                    358:                                           "IRQ.\n"
                    359:                                           KERN_WARNING "It will not be activated.\n",
                    360:                                   pci_tbl[chip_idx].name);
                    361:                        continue;
                    362:                }
                    363: 
                    364:                if ((pciaddr & PCI_BASE_ADDRESS_SPACE_IO)) {
                    365:                        ioaddr = pciaddr & PCI_BASE_ADDRESS_IO_MASK;
                    366:                        if (check_region(ioaddr, pci_tbl[chip_idx].io_size))
                    367:                                continue;
                    368:                } else if ((ioaddr = (long)ioremap(pciaddr & PCI_BASE_ADDRESS_MEM_MASK,
                    369:                                                                                   pci_tbl[chip_idx].io_size)) == 0) {
                    370:                        printk(KERN_INFO "Failed to map PCI address %#lx.\n",
                    371:                                   pciaddr);
                    372:                        continue;
                    373:                }
                    374: 
                    375:                if ( ! (pci_flags & PCI_NO_ACPI_WAKE))
                    376:                        acpi_wake(pdev);
                    377:                pcibios_read_config_word(pci_bus, pci_device_fn,
                    378:                                                                 PCI_COMMAND, &pci_command);
                    379:                new_command = pci_command | (pci_flags & 7);
                    380:                if (pci_command != new_command) {
                    381:                        printk(KERN_INFO "  The PCI BIOS has not enabled the"
                    382:                                   " device at %d/%d!  Updating PCI command %4.4x->%4.4x.\n",
                    383:                                   pci_bus, pci_device_fn, pci_command, new_command);
                    384:                        pcibios_write_config_word(pci_bus, pci_device_fn,
                    385:                                                                          PCI_COMMAND, new_command);
                    386:                }
                    387: 
                    388:                newdev = drv_id->probe1(pdev, initial_device,
                    389:                                                           ioaddr, irq, chip_idx, cards_found);
                    390: 
                    391:                if (newdev  && (pci_flags & PCI_COMMAND_MASTER)  &&
                    392:                        ! (pci_flags & PCI_NO_MIN_LATENCY)) {
                    393:                        u8 pci_latency;
                    394:                        pcibios_read_config_byte(pci_bus, pci_device_fn,
                    395:                                                                         PCI_LATENCY_TIMER, &pci_latency);
                    396:                        if (pci_latency < min_pci_latency) {
                    397:                                printk(KERN_INFO "  PCI latency timer (CFLT) is "
                    398:                                           "unreasonably low at %d.  Setting to %d clocks.\n",
                    399:                                           pci_latency, min_pci_latency);
                    400:                                pcibios_write_config_byte(pci_bus, pci_device_fn,
                    401:                                                                                  PCI_LATENCY_TIMER, min_pci_latency);
                    402:                        }
                    403:                }
                    404:                if (newdev) {
                    405:                        struct dev_info *devp =
                    406:                                kmalloc(sizeof(struct dev_info), GFP_KERNEL);
                    407:                        if (devp) {
                    408:                                devp->next = dev_list;
                    409:                                devp->dev = newdev;
                    410:                                devp->drv_id = drv_id;
                    411:                                dev_list = devp;
                    412:                        }
                    413:                }
                    414:                initial_device = 0;
                    415:                cards_found++;
                    416:        }
                    417: 
                    418:        if (((drv_id->flags & PCI_HOTSWAP)
                    419:                 && register_hotswap_hook && (*register_hotswap_hook)(drv_id) == 0)
                    420:                || cards_found) {
                    421:                MOD_INC_USE_COUNT;
                    422:                drv_id->next = drv_list;
                    423:                drv_list = drv_id;
                    424:                return 0;
                    425:        } else
                    426:                return cards_found ? 0 : -ENODEV;
                    427: }
                    428: #endif
                    429: 
                    430: void pci_drv_unregister(struct drv_id_info *drv_id)
                    431: {
                    432:        struct drv_id_info **drvp;
                    433:        struct dev_info **devip = &dev_list;
                    434: 
                    435:        if (unregister_hotswap_hook)
                    436:                (*unregister_hotswap_hook)(drv_id);
                    437: 
                    438:        for (drvp = &drv_list; *drvp; drvp = &(*drvp)->next)
                    439:                if (*drvp == drv_id) {
                    440:                        *drvp = (*drvp)->next;
                    441:                        MOD_DEC_USE_COUNT;
                    442:                        break;
                    443:                }
                    444:        while (*devip) {
                    445:                struct dev_info *thisdevi = *devip;
                    446:                if (thisdevi->drv_id == drv_id) {
                    447:                        *devip = thisdevi->next;
                    448:                        kfree(thisdevi);
                    449:                } else
                    450:                        devip = &(*devip)->next;
                    451:        }
                    452: 
                    453:        return;
                    454: }
                    455: 
                    456: #if LINUX_VERSION_CODE < 0x20400
                    457: /*
                    458:   Search PCI configuration space for the specified capability registers.
                    459:   Return the index, or 0 on failure.
                    460:   The 2.4 kernel now includes this function.
                    461: */
                    462: int pci_find_capability(struct pci_dev *pdev, int findtype)
                    463: {
                    464:        u16 pci_status, cap_type;
                    465:        u8 pci_cap_idx;
                    466:        int cap_idx;
                    467: 
                    468:        pci_read_config_word(pdev, PCI_STATUS, &pci_status);
                    469:        if ( ! (pci_status & PCI_STATUS_CAP_LIST))
                    470:                return 0;
                    471:        pci_read_config_byte(pdev, PCI_CAPABILITY_LIST, &pci_cap_idx);
                    472:        cap_idx = pci_cap_idx;
                    473:        for (cap_idx = pci_cap_idx; cap_idx; cap_idx = (cap_type >> 8) & 0xff) {
                    474:                pci_read_config_word(pdev, cap_idx, &cap_type);
                    475:                if ((cap_type & 0xff) == findtype)
                    476:                        return cap_idx;
                    477:        }
                    478:        return 0;
                    479: }
                    480: #endif
                    481: 
                    482: /* Change a device from D3 (sleep) to D0 (active).
                    483:    Return the old power state.
                    484:    This is more complicated than you might first expect since most cards
                    485:    forget all PCI config info during the transition! */
                    486: int acpi_wake(struct pci_dev *pdev)
                    487: {
                    488:        u32 base[5], romaddr;
                    489:        u16 pci_command, pwr_command;
                    490:        u8  pci_latency, pci_cacheline, irq;
                    491:        int i, pwr_cmd_idx = pci_find_capability(pdev, PCI_CAP_ID_PM);
                    492: 
                    493:        if (pwr_cmd_idx == 0)
                    494:                return 0;
                    495:        pci_read_config_word(pdev, pwr_cmd_idx + 4, &pwr_command);
                    496:        if ((pwr_command & 3) == 0)
                    497:                return 0;
                    498:        pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
                    499:        for (i = 0; i < 5; i++)
                    500:                pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0 + i*4,
                    501:                                                                  &base[i]);
                    502:        pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &romaddr);
                    503:        pci_read_config_byte( pdev, PCI_LATENCY_TIMER, &pci_latency);
                    504:        pci_read_config_byte( pdev, PCI_CACHE_LINE_SIZE, &pci_cacheline);
                    505:        pci_read_config_byte( pdev, PCI_INTERRUPT_LINE, &irq);
                    506: 
                    507:        pci_write_config_word(pdev, pwr_cmd_idx + 4, 0x0000);
                    508:        for (i = 0; i < 5; i++)
                    509:                if (base[i])
                    510:                        pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0 + i*4,
                    511:                                                                           base[i]);
                    512:        pci_write_config_dword(pdev, PCI_ROM_ADDRESS, romaddr);
                    513:        pci_write_config_byte( pdev, PCI_INTERRUPT_LINE, irq);
                    514:        pci_write_config_byte( pdev, PCI_CACHE_LINE_SIZE, pci_cacheline);
                    515:        pci_write_config_byte( pdev, PCI_LATENCY_TIMER, pci_latency);
                    516:        pci_write_config_word( pdev, PCI_COMMAND, pci_command | 5);
                    517:        return pwr_command & 3;
                    518: }
                    519: 
                    520: int acpi_set_pwr_state(struct pci_dev *pdev, enum acpi_pwr_state new_state)
                    521: {
                    522:        u16 pwr_command;
                    523:        int pwr_cmd_idx = pci_find_capability(pdev, PCI_CAP_ID_PM);
                    524: 
                    525:        if (pwr_cmd_idx == 0)
                    526:                return 0;
                    527:        pci_read_config_word(pdev, pwr_cmd_idx + 4, &pwr_command);
                    528:        if ((pwr_command & 3) == ACPI_D3  &&  new_state != ACPI_D3)
                    529:                acpi_wake(pdev);                /* The complicated sequence. */
                    530:        pci_write_config_word(pdev, pwr_cmd_idx + 4,
                    531:                                                          (pwr_command & ~3) | new_state);
                    532:        return pwr_command & 3;
                    533: }
                    534: 
                    535: #if defined(CONFIG_PM)
                    536: static int handle_pm_event(struct pm_dev *dev, int event, void *data)
                    537: {
                    538:        static int down = 0;
                    539:        struct dev_info *devi;
                    540:        int pwr_cmd = -1;
                    541: 
                    542:        if (msg_level > 1)
                    543:                printk(KERN_DEBUG "pci-scan: Handling power event %d for driver "
                    544:                           "list %s...\n",
                    545:                           event, drv_list->name);
                    546:        switch (event) {
                    547:        case PM_SUSPEND:
                    548:                if (down) {
                    549:                        printk(KERN_DEBUG "pci-scan: Received extra suspend event\n");
                    550:                        break;
                    551:                }
                    552:                down = 1;
                    553:                for (devi = dev_list; devi; devi = devi->next)
                    554:                        if (devi->drv_id->pwr_event)
                    555:                                devi->drv_id->pwr_event(devi->dev, DRV_SUSPEND);
                    556:                break;
                    557:        case PM_RESUME:
                    558:                if (!down) {
                    559:                        printk(KERN_DEBUG "pci-scan: Received bogus resume event\n");
                    560:                        break;
                    561:                }
                    562:                for (devi = dev_list; devi; devi = devi->next) {
                    563:                        if (devi->drv_id->pwr_event) {
                    564:                                if (msg_level > 3)
                    565:                                        printk(KERN_DEBUG "pci-scan: Calling resume for %s "
                    566:                                                   "device.\n", devi->drv_id->name);
                    567:                                devi->drv_id->pwr_event(devi->dev, DRV_RESUME);
                    568:                        }
                    569:                }
                    570:                down = 0;
                    571:                break;
                    572:        case PM_SET_WAKEUP: pwr_cmd = DRV_PWR_WakeOn; break;
                    573:        case PM_EJECT:          pwr_cmd = DRV_DETACH;   break;
                    574:        default:
                    575:                printk(KERN_DEBUG "pci-scan: Unknown power management event %d.\n",
                    576:                           event);
                    577:        }
                    578:        if (pwr_cmd >= 0)
                    579:                for (devi = dev_list; devi; devi = devi->next)
                    580:                        if (devi->drv_id->pwr_event)
                    581:                                devi->drv_id->pwr_event(devi->dev, pwr_cmd);
                    582: 
                    583:        return 0;
                    584: }
                    585: 
                    586: #elif defined(CONFIG_APM)  &&  LINUX_VERSION_CODE < 0x20400 
                    587: static int handle_apm_event(apm_event_t event)
                    588: {
                    589:        static int down = 0;
                    590:        struct dev_info *devi;
                    591: 
                    592:        if (msg_level > 1)
                    593:                printk(KERN_DEBUG "pci-scan: Handling APM event %d for driver "
                    594:                           "list %s...\n",
                    595:                           event, drv_list->name);
                    596:        return 0;
                    597:        switch (event) {
                    598:        case APM_SYS_SUSPEND:
                    599:        case APM_USER_SUSPEND:
                    600:                if (down) {
                    601:                        printk(KERN_DEBUG "pci-scan: Received extra suspend event\n");
                    602:                        break;
                    603:                }
                    604:                down = 1;
                    605:                for (devi = dev_list; devi; devi = devi->next)
                    606:                        if (devi->drv_id->pwr_event)
                    607:                                devi->drv_id->pwr_event(devi->dev, DRV_SUSPEND);
                    608:                break;
                    609:        case APM_NORMAL_RESUME:
                    610:        case APM_CRITICAL_RESUME:
                    611:                if (!down) {
                    612:                        printk(KERN_DEBUG "pci-scan: Received bogus resume event\n");
                    613:                        break;
                    614:                }
                    615:                for (devi = dev_list; devi; devi = devi->next)
                    616:                        if (devi->drv_id->pwr_event)
                    617:                                devi->drv_id->pwr_event(devi->dev, DRV_RESUME);
                    618:                down = 0;
                    619:                break;
                    620:        }
                    621:        return 0;
                    622: }
                    623: #endif /* CONFIG_APM */
                    624: 
                    625: #ifdef MODULE
                    626: int init_module(void)
                    627: {
                    628:        if (msg_level)  /* Emit version even if no cards detected. */
                    629:                printk(KERN_INFO "%s", version);
                    630: 
                    631: #if defined(CONFIG_PM)
                    632:        pm_register(PM_PCI_DEV, 0, &handle_pm_event);
                    633: #elif defined(CONFIG_APM)  &&  LINUX_VERSION_CODE < 0x20400 
                    634:        apm_register_callback(&handle_apm_event);
                    635: #endif
                    636:        return 0;
                    637: }
                    638: void cleanup_module(void)
                    639: {
                    640: #if defined(CONFIG_PM)
                    641:        pm_unregister_all(&handle_pm_event);
                    642: #elif defined(CONFIG_APM)  &&  LINUX_VERSION_CODE < 0x20400 
                    643:        apm_unregister_callback(&handle_apm_event);
                    644: #endif
                    645:        if (dev_list != NULL)
                    646:                printk(KERN_WARNING "pci-scan: Unfreed device references.\n");
                    647:        return;
                    648: }
                    649: #endif
                    650: 
                    651: 
                    652: /*
                    653:  * Local variables:
                    654:  *  compile-command: "gcc -DMODULE -D__KERNEL__ -DEXPORT_SYMTAB -Wall -Wstrict-prototypes -O6 -c pci-scan.c"
                    655:  *  c-indent-level: 4
                    656:  *  c-basic-offset: 4
                    657:  *  tab-width: 4
                    658:  * End:
                    659:  */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.