pci.c (572d053e1742f6434187ae06fa4b4336fe4439c6) pci.c (06915ea69a48dd223d1612cefc20795c2d38d359)
1/*
2 * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 9 unchanged lines hidden (view full) ---

18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
1/*
2 * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 9 unchanged lines hidden (view full) ---

18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * $Id: pci.c,v 1.85 1998/08/13 19:12:20 gibbs Exp $
26 * $Id: pci.c,v 1.86 1998/09/06 22:41:41 tegge Exp $
27 *
28 */
29
30#include "pci.h"
31#if NPCI > 0
32
33#include "opt_devfs.h"
34#include "opt_simos.h"
35
36#include <sys/param.h>
37#include <sys/systm.h>
38#include <sys/malloc.h>
39#include <sys/fcntl.h>
40#include <sys/conf.h>
41#include <sys/kernel.h>
27 *
28 */
29
30#include "pci.h"
31#if NPCI > 0
32
33#include "opt_devfs.h"
34#include "opt_simos.h"
35
36#include <sys/param.h>
37#include <sys/systm.h>
38#include <sys/malloc.h>
39#include <sys/fcntl.h>
40#include <sys/conf.h>
41#include <sys/kernel.h>
42#include <sys/queue.h>
43#include <sys/types.h>
44#include <sys/buf.h>
42#ifdef DEVFS
43#include <sys/devfsext.h>
44#endif /* DEVFS */
45
46#include <vm/vm.h>
47#include <vm/pmap.h>
45#ifdef DEVFS
46#include <sys/devfsext.h>
47#endif /* DEVFS */
48
49#include <vm/vm.h>
50#include <vm/pmap.h>
51#include <vm/vm_extern.h>
48
49#include <pci/pcireg.h>
50#include <pci/pcivar.h>
51#include <pci/pci_ioctl.h>
52
53#ifdef APIC_IO
54#include <machine/smp.h>
55#endif /* APIC_IO */
56
52
53#include <pci/pcireg.h>
54#include <pci/pcivar.h>
55#include <pci/pci_ioctl.h>
56
57#ifdef APIC_IO
58#include <machine/smp.h>
59#endif /* APIC_IO */
60
61STAILQ_HEAD(devlist, pci_devinfo) pci_devq;
62u_int32_t pci_numdevs = 0;
63u_int32_t pci_generation = 0;
64
57/* return highest PCI bus number known to be used, or -1 if none */
58
59static int
60pci_bushigh(void)
61{
62 if (pci_cfgopen() == 0)
63 return (-1);
64 return (0);

--- 235 unchanged lines hidden (view full) ---

300 cfg->map = pci_readmaps(cfg, PCI_MAXMAPS_2);
301 cfg->hdrspec = pci_readpcb(cfg);
302 break;
303 }
304}
305
306/* read configuration header into pcicfgrect structure */
307
65/* return highest PCI bus number known to be used, or -1 if none */
66
67static int
68pci_bushigh(void)
69{
70 if (pci_cfgopen() == 0)
71 return (-1);
72 return (0);

--- 235 unchanged lines hidden (view full) ---

308 cfg->map = pci_readmaps(cfg, PCI_MAXMAPS_2);
309 cfg->hdrspec = pci_readpcb(cfg);
310 break;
311 }
312}
313
314/* read configuration header into pcicfgrect structure */
315
308static pcicfgregs *
316static struct pci_devinfo *
309pci_readcfg(pcicfgregs *probe)
310{
311 pcicfgregs *cfg = NULL;
317pci_readcfg(pcicfgregs *probe)
318{
319 pcicfgregs *cfg = NULL;
320 struct pci_devinfo *devlist_entry;
321 struct devlist *devlist_head;
312
322
323 devlist_head = &pci_devq;
324
325 devlist_entry = NULL;
326
313 if (pci_cfgread(probe, PCIR_DEVVENDOR, 4) != -1) {
327 if (pci_cfgread(probe, PCIR_DEVVENDOR, 4) != -1) {
314 cfg = malloc(sizeof (pcicfgregs), M_DEVBUF, M_WAITOK);
315 if (cfg == NULL)
316 return (cfg);
328 devlist_entry = malloc(sizeof(struct pci_devinfo),
329 M_DEVBUF, M_WAITOK);
330 if (devlist_entry == NULL)
331 return (NULL);
317
332
333 cfg = &devlist_entry->cfg;
334
318 bzero(cfg, sizeof *cfg);
319
320 cfg->bus = probe->bus;
321 cfg->slot = probe->slot;
322 cfg->func = probe->func;
335 bzero(cfg, sizeof *cfg);
336
337 cfg->bus = probe->bus;
338 cfg->slot = probe->slot;
339 cfg->func = probe->func;
323 cfg->parent = probe->parent;
324
325 cfg->vendor = pci_cfgread(cfg, PCIR_VENDOR, 2);
326 cfg->device = pci_cfgread(cfg, PCIR_DEVICE, 2);
327 cfg->cmdreg = pci_cfgread(cfg, PCIR_COMMAND, 2);
328 cfg->statreg = pci_cfgread(cfg, PCIR_STATUS, 2);
329 cfg->baseclass = pci_cfgread(cfg, PCIR_CLASS, 1);
330 cfg->subclass = pci_cfgread(cfg, PCIR_SUBCLASS, 1);
331 cfg->progif = pci_cfgread(cfg, PCIR_PROGIF, 1);
332 cfg->revid = pci_cfgread(cfg, PCIR_REVID, 1);

--- 37 unchanged lines hidden (view full) ---

370 cfg->mingnt = pci_cfgread(cfg, PCIR_MINGNT, 1);
371 cfg->maxlat = pci_cfgread(cfg, PCIR_MAXLAT, 1);
372
373 cfg->mfdev = (cfg->hdrtype & PCIM_MFDEV) != 0;
374 cfg->hdrtype &= ~PCIM_MFDEV;
375
376 pci_fixancient(cfg);
377 pci_hdrtypedata(cfg);
340 cfg->vendor = pci_cfgread(cfg, PCIR_VENDOR, 2);
341 cfg->device = pci_cfgread(cfg, PCIR_DEVICE, 2);
342 cfg->cmdreg = pci_cfgread(cfg, PCIR_COMMAND, 2);
343 cfg->statreg = pci_cfgread(cfg, PCIR_STATUS, 2);
344 cfg->baseclass = pci_cfgread(cfg, PCIR_CLASS, 1);
345 cfg->subclass = pci_cfgread(cfg, PCIR_SUBCLASS, 1);
346 cfg->progif = pci_cfgread(cfg, PCIR_PROGIF, 1);
347 cfg->revid = pci_cfgread(cfg, PCIR_REVID, 1);

--- 37 unchanged lines hidden (view full) ---

385 cfg->mingnt = pci_cfgread(cfg, PCIR_MINGNT, 1);
386 cfg->maxlat = pci_cfgread(cfg, PCIR_MAXLAT, 1);
387
388 cfg->mfdev = (cfg->hdrtype & PCIM_MFDEV) != 0;
389 cfg->hdrtype &= ~PCIM_MFDEV;
390
391 pci_fixancient(cfg);
392 pci_hdrtypedata(cfg);
393
394 STAILQ_INSERT_TAIL(devlist_head, devlist_entry, pci_links);
395
396 devlist_entry->conf.pc_sel.pc_bus = cfg->bus;
397 devlist_entry->conf.pc_sel.pc_dev = cfg->slot;
398 devlist_entry->conf.pc_sel.pc_func = cfg->func;
399 devlist_entry->conf.pc_hdr = cfg->hdrtype;
400
401 devlist_entry->conf.pc_subvendor = cfg->subvendor;
402 devlist_entry->conf.pc_subdevice = cfg->subdevice;
403 devlist_entry->conf.pc_vendor = cfg->vendor;
404 devlist_entry->conf.pc_device = cfg->device;
405
406 devlist_entry->conf.pc_class = cfg->baseclass;
407 devlist_entry->conf.pc_subclass = cfg->subclass;
408 devlist_entry->conf.pc_progif = cfg->progif;
409 devlist_entry->conf.pc_revid = cfg->revid;
410
411 pci_numdevs++;
412 pci_generation++;
378 }
413 }
379 return (cfg);
414 return (devlist_entry);
380}
381
382#if 0
383/* free pcicfgregs structure and all depending data structures */
384
385static int
415}
416
417#if 0
418/* free pcicfgregs structure and all depending data structures */
419
420static int
386pci_freecfg(pcicfgregs *cfg)
421pci_freecfg(struct pci_devinfo *dinfo)
387{
422{
388 if (cfg->hdrspec != NULL)
389 free(cfg->hdrspec, M_DEVBUF);
390 if (cfg->map != NULL)
391 free(cfg->map, M_DEVBUF);
392 free(cfg, M_DEVBUF);
423 struct devlist *devlist_head;
424
425 devlist_head = &pci_devq;
426
427 if (dinfo->cfg.hdrspec != NULL)
428 free(dinfo->cfg.hdrspec, M_DEVBUF);
429 if (dinfo->cfg.map != NULL)
430 free(dinfo->cfg.map, M_DEVBUF);
431 /* XXX this hasn't been tested */
432 STAILQ_REMOVE(devlist_head, dinfo, pci_devinfo, pci_links);
433 free(dinfo, M_DEVBUF);
434
435 /* increment the generation count */
436 pci_generation++;
437
438 /* we're losing one device */
439 pci_numdevs--;
393 return (0);
394}
395#endif
396
397static void
440 return (0);
441}
442#endif
443
444static void
398pci_addcfg(pcicfgregs *cfg)
445pci_addcfg(struct pci_devinfo *dinfo)
399{
400 if (bootverbose) {
401 int i;
446{
447 if (bootverbose) {
448 int i;
449 pcicfgregs *cfg = &dinfo->cfg;
450
402 printf("found->\tvendor=0x%04x, dev=0x%04x, revid=0x%02x\n",
403 cfg->vendor, cfg->device, cfg->revid);
404 printf("\tclass=%02x-%02x-%02x, hdrtype=0x%02x, mfdev=%d\n",
405 cfg->baseclass, cfg->subclass, cfg->progif,
406 cfg->hdrtype, cfg->mfdev);
407#ifdef PCI_DEBUG
408 printf("\tcmdreg=0x%04x, statreg=0x%04x, cachelnsz=%d (dwords)\n",
409 cfg->cmdreg, cfg->statreg, cfg->cachelnsz);

--- 5 unchanged lines hidden (view full) ---

415 printf("\tintpin=%c, irq=%d\n", cfg->intpin +'a' -1, cfg->intline);
416
417 for (i = 0; i < cfg->nummaps; i++) {
418 pcimap *m = &cfg->map[i];
419 printf("\tmap[%d]: type %x, range %2d, base %08x, size %2d\n",
420 i, m->type, m->ln2range, m->base, m->ln2size);
421 }
422 }
451 printf("found->\tvendor=0x%04x, dev=0x%04x, revid=0x%02x\n",
452 cfg->vendor, cfg->device, cfg->revid);
453 printf("\tclass=%02x-%02x-%02x, hdrtype=0x%02x, mfdev=%d\n",
454 cfg->baseclass, cfg->subclass, cfg->progif,
455 cfg->hdrtype, cfg->mfdev);
456#ifdef PCI_DEBUG
457 printf("\tcmdreg=0x%04x, statreg=0x%04x, cachelnsz=%d (dwords)\n",
458 cfg->cmdreg, cfg->statreg, cfg->cachelnsz);

--- 5 unchanged lines hidden (view full) ---

464 printf("\tintpin=%c, irq=%d\n", cfg->intpin +'a' -1, cfg->intline);
465
466 for (i = 0; i < cfg->nummaps; i++) {
467 pcimap *m = &cfg->map[i];
468 printf("\tmap[%d]: type %x, range %2d, base %08x, size %2d\n",
469 i, m->type, m->ln2range, m->base, m->ln2size);
470 }
471 }
423 pci_drvattach(cfg); /* XXX currently defined in pci_compat.c */
472 pci_drvattach(dinfo); /* XXX currently defined in pci_compat.c */
424}
425
426/* return pointer to device that is a bridge to this bus */
427
428static pcicfgregs *
429pci_bridgeto(int bus)
430{
431 return (NULL); /* XXX not yet implemented */

--- 8 unchanged lines hidden (view full) ---

440 int bushigh = bus;
441
442#ifdef SIMOS
443#undef PCI_SLOTMAX
444#define PCI_SLOTMAX 0
445#endif
446
447 bzero(&probe, sizeof probe);
473}
474
475/* return pointer to device that is a bridge to this bus */
476
477static pcicfgregs *
478pci_bridgeto(int bus)
479{
480 return (NULL); /* XXX not yet implemented */

--- 8 unchanged lines hidden (view full) ---

489 int bushigh = bus;
490
491#ifdef SIMOS
492#undef PCI_SLOTMAX
493#define PCI_SLOTMAX 0
494#endif
495
496 bzero(&probe, sizeof probe);
448 probe.parent = pci_bridgeto(bus);
497 /* XXX KDM */
498 /* probe.parent = pci_bridgeto(bus); */
449 probe.bus = bus;
450 for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) {
451 int pcifunchigh = 0;
452 for (probe.func = 0; probe.func <= pcifunchigh; probe.func++) {
499 probe.bus = bus;
500 for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) {
501 int pcifunchigh = 0;
502 for (probe.func = 0; probe.func <= pcifunchigh; probe.func++) {
453 pcicfgregs *cfg = pci_readcfg(&probe);
454 if (cfg != NULL) {
455 if (cfg->mfdev)
503 struct pci_devinfo *dinfo = pci_readcfg(&probe);
504 if (dinfo != NULL) {
505 if (dinfo->cfg.mfdev)
456 pcifunchigh = 7;
457 /*
458 * XXX: Temporarily move pci_addcfg() up before
459 * the use of cfg->subordinatebus. This is
460 * necessary, since pci_addcfg() calls the
461 * device's probe(), which may read the bus#
462 * from some device dependent register of
463 * some host to PCI bridges. The probe will
464 * eventually be moved to pci_readcfg(), and
465 * pci_addcfg() will then be moved back down
466 * below the conditional statement ...
467 */
506 pcifunchigh = 7;
507 /*
508 * XXX: Temporarily move pci_addcfg() up before
509 * the use of cfg->subordinatebus. This is
510 * necessary, since pci_addcfg() calls the
511 * device's probe(), which may read the bus#
512 * from some device dependent register of
513 * some host to PCI bridges. The probe will
514 * eventually be moved to pci_readcfg(), and
515 * pci_addcfg() will then be moved back down
516 * below the conditional statement ...
517 */
468 pci_addcfg(cfg);
518 pci_addcfg(dinfo);
469
519
470 if (bushigh < cfg->subordinatebus)
471 bushigh = cfg->subordinatebus;
520 if (bushigh < dinfo->cfg.subordinatebus)
521 bushigh = dinfo->cfg.subordinatebus;
472
522
473 cfg = NULL; /* we don't own this anymore ... */
523 /* XXX KDM */
524 /* cfg = NULL; we don't own this anymore ... */
474 }
475 }
476 }
477 return (bushigh);
478}
479
480/* scan a PCI bus tree reached through one PCI attachment point */
481
482int
483pci_probe(pciattach *parent)
484{
485 int bushigh;
486 int bus = 0;
487
525 }
526 }
527 }
528 return (bushigh);
529}
530
531/* scan a PCI bus tree reached through one PCI attachment point */
532
533int
534pci_probe(pciattach *parent)
535{
536 int bushigh;
537 int bus = 0;
538
539 STAILQ_INIT(&pci_devq);
540
488 bushigh = pci_bushigh();
489 while (bus <= bushigh) {
490 int newbushigh;
491
492 printf("Probing for devices on PCI bus %d:\n", bus);
493 newbushigh = pci_probebus(bus);
494
495 if (bushigh < newbushigh)

--- 17 unchanged lines hidden (view full) ---

513}
514
515static int
516pci_close(dev_t dev, int flag, int devtype, struct proc *p)
517{
518 return 0;
519}
520
541 bushigh = pci_bushigh();
542 while (bus <= bushigh) {
543 int newbushigh;
544
545 printf("Probing for devices on PCI bus %d:\n", bus);
546 newbushigh = pci_probebus(bus);
547
548 if (bushigh < newbushigh)

--- 17 unchanged lines hidden (view full) ---

566}
567
568static int
569pci_close(dev_t dev, int flag, int devtype, struct proc *p)
570{
571 return 0;
572}
573
574/*
575 * Match a single pci_conf structure against an array of pci_match_conf
576 * structures. The first argument, 'matches', is an array of num_matches
577 * pci_match_conf structures. match_buf is a pointer to the pci_conf
578 * structure that will be compared to every entry in the matches array.
579 * This function returns 1 on failure, 0 on success.
580 */
521static int
581static int
582pci_conf_match(struct pci_match_conf *matches, int num_matches,
583 struct pci_conf *match_buf)
584{
585 int i;
586
587 if ((matches == NULL) || (match_buf == NULL) || (num_matches <= 0))
588 return(1);
589
590 for (i = 0; i < num_matches; i++) {
591 /*
592 * I'm not sure why someone would do this...but...
593 */
594 if (matches[i].flags == PCI_GETCONF_NO_MATCH)
595 continue;
596
597 /*
598 * Look at each of the match flags. If it's set, do the
599 * comparison. If the comparison fails, we don't have a
600 * match, go on to the next item if there is one.
601 */
602 if (((matches[i].flags & PCI_GETCONF_MATCH_BUS) != 0)
603 && (match_buf->pc_sel.pc_bus != matches[i].pc_sel.pc_bus))
604 continue;
605
606 if (((matches[i].flags & PCI_GETCONF_MATCH_DEV) != 0)
607 && (match_buf->pc_sel.pc_dev != matches[i].pc_sel.pc_dev))
608 continue;
609
610 if (((matches[i].flags & PCI_GETCONF_MATCH_FUNC) != 0)
611 && (match_buf->pc_sel.pc_func != matches[i].pc_sel.pc_func))
612 continue;
613
614 if (((matches[i].flags & PCI_GETCONF_MATCH_VENDOR) != 0)
615 && (match_buf->pc_vendor != matches[i].pc_vendor))
616 continue;
617
618 if (((matches[i].flags & PCI_GETCONF_MATCH_DEVICE) != 0)
619 && (match_buf->pc_device != matches[i].pc_device))
620 continue;
621
622 if (((matches[i].flags & PCI_GETCONF_MATCH_CLASS) != 0)
623 && (match_buf->pc_class != matches[i].pc_class))
624 continue;
625
626 if (((matches[i].flags & PCI_GETCONF_MATCH_UNIT) != 0)
627 && (match_buf->pd_unit != matches[i].pd_unit))
628 continue;
629
630 if (((matches[i].flags & PCI_GETCONF_MATCH_NAME) != 0)
631 && (strncmp(matches[i].pd_name, match_buf->pd_name,
632 sizeof(match_buf->pd_name)) != 0))
633 continue;
634
635 return(0);
636 }
637
638 return(1);
639}
640
641static int
522pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
523{
524 struct pci_io *io;
525 int error;
526
642pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
643{
644 struct pci_io *io;
645 int error;
646
527 if (cmd != PCIOCGETCONF && !(flag & FWRITE))
647 if (!(flag & FWRITE))
528 return EPERM;
529
648 return EPERM;
649
650
530 switch(cmd) {
531 case PCIOCGETCONF:
651 switch(cmd) {
652 case PCIOCGETCONF:
532#ifdef NOTYET
533static struct pci_conf *pci_dev_list;
534static unsigned pci_dev_list_count;
535static unsigned pci_dev_list_size;
653 {
654 struct pci_devinfo *dinfo;
655 struct pci_conf_io *cio;
656 struct devlist *devlist_head;
657 struct pci_match_conf *pattern_buf;
658 int num_patterns;
659 size_t iolen;
660 int ionum, i;
536
537 cio = (struct pci_conf_io *)data;
661
662 cio = (struct pci_conf_io *)data;
538 iolen = min(cio->pci_len,
539 pci_dev_list_count * sizeof(struct pci_conf));
540 cio->pci_len = pci_dev_list_count * sizeof(struct pci_conf);
541
663
542 error = copyout(pci_dev_list, cio->pci_buf, iolen);
543#else
544 error = ENODEV;
545#endif
546 break;
664 num_patterns = 0;
665 dinfo = NULL;
666
667 /*
668 * Hopefully the user won't pass in a null pointer, but it
669 * can't hurt to check.
670 */
671 if (cio == NULL) {
672 error = EINVAL;
673 break;
674 }
675
676 /*
677 * If the user specified an offset into the device list,
678 * but the list has changed since they last called this
679 * ioctl, tell them that the list has changed. They will
680 * have to get the list from the beginning.
681 */
682 if ((cio->offset != 0)
683 && (cio->generation != pci_generation)){
684 cio->num_matches = 0;
685 cio->status = PCI_GETCONF_LIST_CHANGED;
686 error = 0;
687 break;
688 }
689
690 /*
691 * Check to see whether the user has asked for an offset
692 * past the end of our list.
693 */
694 if (cio->offset >= pci_numdevs) {
695 cio->num_matches = 0;
696 cio->status = PCI_GETCONF_LAST_DEVICE;
697 error = 0;
698 break;
699 }
700
701 /* get the head of the device queue */
702 devlist_head = &pci_devq;
703
704 /*
705 * Determine how much room we have for pci_conf structures.
706 * Round the user's buffer size down to the nearest
707 * multiple of sizeof(struct pci_conf) in case the user
708 * didn't specify a multiple of that size.
709 */
710 iolen = min(cio->match_buf_len -
711 (cio->match_buf_len % sizeof(struct pci_conf)),
712 pci_numdevs * sizeof(struct pci_conf));
713
714 /*
715 * Since we know that iolen is a multiple of the size of
716 * the pciconf union, it's okay to do this.
717 */
718 ionum = iolen / sizeof(struct pci_conf);
719
720 /*
721 * If this test is true, the user wants the pci_conf
722 * structures returned to match the supplied entries.
723 */
724 if ((cio->num_patterns > 0)
725 && (cio->pat_buf_len > 0)) {
726 /*
727 * pat_buf_len needs to be:
728 * num_patterns * sizeof(struct pci_match_conf)
729 * While it is certainly possible the user just
730 * allocated a large buffer, but set the number of
731 * matches correctly, it is far more likely that
732 * their kernel doesn't match the userland utility
733 * they're using. It's also possible that the user
734 * forgot to initialize some variables. Yes, this
735 * may be overly picky, but I hazard to guess that
736 * it's far more likely to just catch folks that
737 * updated their kernel but not their userland.
738 */
739 if ((cio->num_patterns *
740 sizeof(struct pci_match_conf)) != cio->pat_buf_len){
741 /* The user made a mistake, return an error*/
742 cio->status = PCI_GETCONF_ERROR;
743 printf("pci_ioctl: pat_buf_len %d != "
744 "num_patterns (%d) * sizeof(struct "
745 "pci_match_conf) (%d)\npci_ioctl: "
746 "pat_buf_len should be = %d\n",
747 cio->pat_buf_len, cio->num_patterns,
748 sizeof(struct pci_match_conf),
749 sizeof(struct pci_match_conf) *
750 cio->num_patterns);
751 printf("pci_ioctl: do your headers match your "
752 "kernel?\n");
753 cio->num_matches = 0;
754 error = EINVAL;
755 break;
756 }
757
758 /*
759 * Check the user's buffer to make sure it's readable.
760 */
761 if ((error = useracc((caddr_t)cio->patterns,
762 cio->pat_buf_len, B_READ)) != 1){
763 printf("pci_ioctl: pattern buffer %#lx, "
764 "length %u isn't user accessible for"
765 " READ\n", cio->patterns,
766 cio->pat_buf_len);
767 error = EACCES;
768 break;
769 }
770 /*
771 * Allocate a buffer to hold the patterns.
772 */
773 pattern_buf = malloc(cio->pat_buf_len, M_TEMP,
774 M_WAITOK);
775 error = copyin(cio->patterns, pattern_buf,
776 cio->pat_buf_len);
777 if (error != 0)
778 break;
779 num_patterns = cio->num_patterns;
780
781 } else if ((cio->num_patterns > 0)
782 || (cio->pat_buf_len > 0)) {
783 /*
784 * The user made a mistake, spit out an error.
785 */
786 cio->status = PCI_GETCONF_ERROR;
787 cio->num_matches = 0;
788 printf("pci_ioctl: invalid GETCONF arguments\n");
789 error = EINVAL;
790 break;
791 } else
792 pattern_buf = NULL;
793
794 /*
795 * Make sure we can write to the match buffer.
796 */
797 if ((error = useracc((caddr_t)cio->matches, cio->match_buf_len,
798 B_WRITE)) != 1) {
799 printf("pci_ioctl: match buffer %#lx, length %u "
800 "isn't user accessible for WRITE\n",
801 cio->matches, cio->match_buf_len);
802 error = EACCES;
803 break;
804 }
805
806 /*
807 * Go through the list of devices and copy out the devices
808 * that match the user's criteria.
809 */
810 for (cio->num_matches = 0, error = 0, i = 0,
811 dinfo = STAILQ_FIRST(devlist_head);
812 (dinfo != NULL) && (cio->num_matches < ionum)
813 && (error == 0) && (i < pci_numdevs);
814 dinfo = STAILQ_NEXT(dinfo, pci_links), i++) {
815
816 if (i < cio->offset)
817 continue;
818
819 if ((pattern_buf == NULL) ||
820 (pci_conf_match(pattern_buf, num_patterns,
821 &dinfo->conf) == 0)) {
822
823 /*
824 * If we've filled up the user's buffer,
825 * break out at this point. Since we've
826 * got a match here, we'll pick right back
827 * up at the matching entry. We can also
828 * tell the user that there are more matches
829 * left.
830 */
831 if (cio->num_matches >= ionum)
832 break;
833
834 error = copyout(&dinfo->conf,
835 &cio->matches[cio->num_matches],
836 sizeof(struct pci_conf));
837 cio->num_matches++;
838 }
839 }
840
841 /*
842 * Set the pointer into the list, so if the user is getting
843 * n records at a time, where n < pci_numdevs,
844 */
845 cio->offset = i;
846
847 /*
848 * Set the generation, the user will need this if they make
849 * another ioctl call with offset != 0.
850 */
851 cio->generation = pci_generation;
547
852
853 /*
854 * If this is the last device, inform the user so he won't
855 * bother asking for more devices. If dinfo isn't NULL, we
856 * know that there are more matches in the list because of
857 * the way the traversal is done.
858 */
859 if (dinfo == NULL)
860 cio->status = PCI_GETCONF_LAST_DEVICE;
861 else
862 cio->status = PCI_GETCONF_MORE_DEVS;
863
864 if (pattern_buf != NULL)
865 free(pattern_buf, M_TEMP);
866
867 break;
868 }
548 case PCIOCREAD:
549 io = (struct pci_io *)data;
550 switch(io->pi_width) {
551 pcicfgregs probe;
552 case 4:
553 case 2:
554 case 1:
555 probe.bus = io->pi_sel.pc_bus;

--- 67 unchanged lines hidden ---
869 case PCIOCREAD:
870 io = (struct pci_io *)data;
871 switch(io->pi_width) {
872 pcicfgregs probe;
873 case 4:
874 case 2:
875 case 1:
876 probe.bus = io->pi_sel.pc_bus;

--- 67 unchanged lines hidden ---